ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

http://uoj.ac/problem/14

由于加入的边权递增,可以直接运行kruskal并支持撤销,但这样如果反复批量删边和撤销,时间复杂度会退化,因此需要对删边操作加上延时处理,只有在删边后下一个操作不是撤销时才执行删边。由于有撤销,并查集需要按秩合并且不路径压缩。

#include<bits/stdc++.h>
typedef long long i64;
const int N=500007;
int _(){
    int x;
    scanf("%d",&x);
    return x;
}
int n,m;
int f[N][2];
int po,ep=0,ep1=0;
#define sz f][1
#define fa f][0
int gf(int x){
    while(x!=x[fa])x=x[fa];
    return x;
}
void lk(int x,int y){
    x[fa]=y;
    y[sz]+=x[sz];
}
void ct(int x,int y){
    x[fa]=x;
    y[sz]-=x[sz];
}
struct ev{
    int a,b,ec;
    i64 sum;
    void undo(){ct(a,b);}
}e[N];
void fix(){
    while(ep1<ep)e[ep--].undo();
}
void ae(int v){
    po=0;
    fix();
    ev&e0=e[ep];
    ev&e1=e[ep1=++ep];
    int x=gf(_()),y=gf(_());
    if(x==y){
        e1=(ev){0,0,e0.ec,e0.sum};
    }else{
        if(x[sz]>y[sz])std::swap(x,y);
        lk(x,y);
        e1=(ev){x,y,e0.ec+1,e0.sum+v};
    }
}
void de(){
    po=1;
    fix();
    ep1=ep-_();
}
void undo(){
    if(!po)e[ep--].undo();
    ep1=ep;
}
int main(){
    n=_();m=_();
    for(int i=1;i<=n;++i){
        i[fa]=i;
        i[sz]=1;
    }
    for(int i=1,o;i<=m;++i){
        o=_();
        if(o==2272)ae(i);
        else if(o==2596033)de();
        else undo();
        printf("%lld",e[ep1].ec==n-1?e[ep1].sum:0);
    }
    return 0;
}
View Code

 

posted on 2017-08-16 16:58  nul  阅读(171)  评论(0编辑  收藏  举报