2018.7.17日记&总结

今天只过了4题并且罚时超多,发挥得不好,代码能力堪忧,很多细节注意得不好。
签到题用来1h,太不应该了,因为cout TLE了7发。这种细节一定要注意。还有一开始要调编译C++语言,否则要CE。
过后几道做法一眼秒但是代码还是写了很久,WA了好多发。
特别是单调队列优化DP竟然想了很久,不知道你在干什么!
还有倍增lca写错,这些细节错误真的很不应该。
还有longlong没开,爆int之类的错误。
一定要注意时间的控制。因为后来会发现好多题会做但没时间写。要尽力快的写出自己一眼就会做的简单题,然后才能有时间去做稍难的题。特别是签到的前两题一定要在40分钟内写完。其他想出做法的题尽量1次AC,这样前2小时过4题,后面的题就有时间思考和实现了。

听评讲时要全神贯注,不能开小差。特别时别人讲乱搞做法之类的认真听,学到一点总是好的。谦虚的向别人学习,自己的水平还十分不足,尽量多学各种知识!

今天下午写题效率极低,还一直在购物,你应该知道自己要做什么!!!游完泳会寝室洗完澡都快10点了,然后又聊了会天,拍了会照,就11点了,所以时间转瞬即逝,一定要抓紧时间写题!!

题解:
A:神奇的博弈,性质题,明天研究并写一下。

B:用exgcd的性质转化为求x,y链上所有数的gcd

C:树上有黑,白点,每次修改把白点边黑,求把所有黑点割开所需删边边权最小值。
首先每次删过的边不会再加回来,所以把询问离线,考虑把黑点变成白点,于是就变成找这个黑点周围所有黑点中最大的边加入,把split改成merge就可以用可并堆维护了。
所以这种把询问倒过来做,把分裂改成合并的思路很常见!

#include<bits/stdc++.h>
using namespace std;
#define maxn 100020
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]

typedef long long ll;
struct node{
    int x,y,w;
}e[maxn];
int root[maxn];
struct HEAP{
    int ch[maxn * 2][2];
    int w[maxn * 2],tot,d[maxn * 2],num[maxn * 2];
    void clear(){
        for (int i = 1 ; i <= tot ; i++) ch[i][0] = ch[i][1] = w[i] = d[i] = 0;
        tot = 0;
    }
    int merge(int x,int y){
        if ( !x ) return y;
        if ( !y ) return x;
        if ( w[x] < w[y] ) swap(x,y);
        rs(x) = merge(rs(x),y);
        if ( d[ls(x)] < d[rs(x)] ) swap(ls(x),rs(x));
        d[x] = d[rs(x)] + 1;
        return x;
    }
    int init(int v,int id){
        ++tot;
        ls(tot) = rs(tot) = d[tot] = 0;
        w[tot] = v , num[tot] = id;
        return tot;
    }
    void insert(int x,int v,int id){
        root[x] = merge(root[x],init(v,id));
    }
    int top(int x){
        int cur = root[x];
        root[x] = merge(ls(root[x]),rs(root[x])); //边找根,边删除
        return cur;
    }
}heap;
int a[maxn * 2],tot,q,n,T,col[maxn],fa[maxn],del[maxn * 2];
ll ans[maxn],sum;

void clear(){
    for (int i = 1 ; i <= n ; i++) root[i] = col[i] = del[i] = 0;
    for (int i = 1 ; i <= n ; i++) fa[i] = i;
    tot = 0 , sum = 0;
    heap.clear();
}
int getfa(int x){ return x == fa[x] ? x : fa[x] = getfa(fa[x]); }
void solve(){
    ll cur = sum; tot = q;
    for (int i = 1 ; i <= n ; i++){
        if ( !col[i] ) col[i] = 1 , a[++tot] = i;
    }
    for (int i = 1 ; i < n ; i++){
        heap.insert(e[i].x,e[i].w,i);
        heap.insert(e[i].y,e[i].w,i);
    }
    ans[q] = cur;
    for (int i = tot ; i >= 1 ; i--){
        int x = a[i],y,rt;
        col[x]--;
        if ( !col[x] ){
            x = getfa(x);
            while ( 1 ){
                rt = heap.top(x);
                if ( !rt ) break;
                if ( !del[heap.num[rt]] ){ del[heap.num[rt]] = 1; break; } //直接把删除标记打给边
            }
            if ( rt ){
                cur -= e[heap.num[rt]].w , x = e[heap.num[rt]].x , y = e[heap.num[rt]].y;
                int p = getfa(x) , q = getfa(y);
                fa[p] = q;
                root[q] = heap.merge(root[p],root[q]);
            }
        }
        if ( i <= q + 1 ) ans[i - 1] = cur; //操作之前的答案
    }
    for (int i = 0 ; i <= q ; i++) printf("%lld\n",ans[i]);
//  printf("\n");
}
int main(){
    freopen("input.txt","r",stdin);
    scanf("%d",&T);
    while ( T-- ){
        scanf("%d",&n);
        clear();
        for (int i = 1 ; i <= n ; i++) scanf("%d",&col[i]);
        for (int i = 1 ; i < n ; i++){
            scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].w);
            sum += e[i].w;
        }
        scanf("%d",&q);
        for (int i = 1 ; i <= q ; i++) scanf("%d",&a[i]) , col[a[i]]++;
        solve();
    }
    return 0;
}

D:单调队列优化DP。对每种颜色决策单调右移,注意不是什么决策点单调(因为决策点不好找),直接对每种颜色开一个单调队列即可。STL很好用

E:区间加等差数列。两次差分,维护公差标记

F:数学结论题,快速推结论,
1^2+2^2+3^2+4^2+5^2………………+n^2=n(n+1)(2n+1)/6
但不知道这个结论暴力预处理也可以。
开3次根号可以用pow(x,-1/3)也可以二分。
注意100w的输出绝对不能用cout,并且读入也应该写读入优化。

G:优化状态高斯消元。利用状态的对称性,把状态数/2,就可以过了。所以这种题一定要仔细算一下状态数和可以优化的地方,不能大致想一想1600(/4)^3*10过不了就放弃了。
并且评测机很快的!
还有可以暴力DP500次,利用概率都后面都很小。
这样的高消一定要把转移想清楚,因为没法调,明天写完!

所以今天太休闲没怎么调题,不应该啊!明天振作起来!静心努力!把欠的债补完!后天争取进入前5!

有些事情绝对不能等待,要及时,抓住机会!比如回涵涵消息,要立即回的!

猜你喜欢

转载自blog.csdn.net/weixin_42484877/article/details/81090516