bzoj 2243 染色

来源:互联网 发布:五五开和笑笑 知乎 编辑:程序博客网 时间:2024/06/12 01:29

一个比较裸的树剖题

先考虑区间处理的情况,我们维护区间颜色段数,区间左右端点的颜色之后这就可以满足区间合并了

然后用树剖的方法处理一下就好

ps:用结构体保存区间值重载加号表示区间合并不能更方便

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;const int maxn = 312345;struct Info{    int l,r;    int siz;    void init(int x){        l = r = x;        siz = 1;    }    void clear(){        l = r = siz = -1;    }    Info(){}    Info(int l,int r,int siz):l(l),r(r),siz(siz){}};Info rev(Info v){    return Info(v.r,v.l,v.siz);}Info operator + (Info l,Info r){    if(l.siz == -1) return r;    if(r.siz == -1) return l;    Info ret(l.l,r.r,l.siz+r.siz);    if(l.r == r.l)        ret.siz--;    return ret;}Info info[maxn*4];int lazy[maxn*4];#define root 1,1,n#define Now int o,int l,int r#define Mid int m = l + (r - l)/2#define lson o<<1,l,m#define rson o<<1|1,m+1,rvoid push_down(Now){    int v = lazy[o];    lazy[o] = -1;    if(l != r){        info[o<<1].init(v);        info[o<<1|1].init(v);        lazy[o<<1] = lazy[o<<1|1] = v;    }}void update(Now,int ul,int ur,int v){    if(ul <= l && r <= ur){        lazy[o] = v;        info[o].init(v);        return;    }    Mid;    if(lazy[o] != -1)push_down(o,l,r);    if(ul <= m)      update(lson,ul,ur,v);    if(m+1 <= ur)    update(rson,ul,ur,v);    info[o] = info[o<<1] + info[o<<1|1];}Info query(Now,int ql,int qr){    if(ql <= l && r <= qr)        return info[o];    Mid;    if(lazy[o] != -1)        push_down(o,l,r);    Info ret;    ret.clear();    if(ql <= m)   ret = query(lson,ql,qr) + ret;    if(m+1 <= qr) ret = ret + query(rson,ql,qr);    return ret;}void sinit(){    memset(lazy,-1,sizeof(lazy));}//---treesplitevector<int> edge[maxn];void Link(int st,int ed){    edge[st].push_back(ed);    edge[ed].push_back(st);}void init(int n){    for(int i=0;i<=n;i++){        edge[i].clear();    }}int fa[maxn],son[maxn],siz[maxn];int deep[maxn],top[maxn],tid[maxn];int _cnt;void dffs(int st,int Fa,int Deep){    son[st] = -1,fa[st] = Fa;    deep[st] = Deep,siz[st] = 1;    for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){        int x = *it;        if( x != Fa){            dffs(x,st,Deep+1);            siz[st] += siz[x];            if(son[st] == -1 || siz[son[st]] < siz[x])                son[st] = x;        }    }}void dfss(int st,int Top){    tid[st] = _cnt ++;    top[st] = Top;    if(son[st] != -1){        dfss(son[st],Top);    }    for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){        int x = *it;        if(x != fa[st] && x != son[st]){            dfss(x,x);        }    }}void splite(){    _cnt = 1;    dffs(1,-1,1);    dfss(1,1);}int n;void UPD(int x,int y,int v){    int tx,ty;    tx = top[x],ty = top[y];    while(tx != ty){        if(deep[tx] < deep[ty]){            swap(x,y),swap(tx,ty);        }        update(root,tid[tx],tid[x],v);        x = fa[tx],tx = top[x];    }    if(deep[x] < deep[y])        swap(x,y);    update(root,tid[y],tid[x],v);}Info QUE(int x,int y){    Info X,Y;    X.clear();    Y.clear();    int tx,ty;    tx = top[x],ty = top[y];    while(tx != ty){        if(deep[tx] < deep[ty])            swap(x,y),swap(X,Y),swap(tx,ty);        X = query(root,tid[tx],tid[x]) + X;        x = fa[tx],tx = top[x];    }    if(deep[x] < deep[y])        swap(x,y),swap(X,Y);    return rev(X) + rev(query(root,tid[y],tid[x])) + Y;}int arr[maxn];int main(){    int m;    while(~scanf("%d %d",&n,&m)){        for(int i=1;i<=n;i++){            scanf("%d",&arr[i]);        }        init(n);        int x,y;        for(int i=1;i<n;i++){            scanf("%d %d",&x,&y);            Link(x,y);        }        splite();        sinit();        for(int i=1;i<=n;i++){            update(root,tid[i],tid[i],arr[i]);        }        int v;        char ord[3];        while(m--){            scanf("%s",ord);            scanf("%d %d",&x,&y);            if(*ord == 'Q'){                printf("%d\n",QUE(x,y).siz);            }            else{                scanf("%d",&v);                UPD(x,y,v);            }        }    }    return 0;}

初始化的时候把lazy memset成0的丝薄应该只有我

还有树剖查询的时候忘记加上原来的区间直接赋值的也是没谁了。。。

0 0
原创粉丝点击