bzoj 2243 染色

一个比较裸的树剖题

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

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

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,r

void 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));
}

//---treesplite

vector<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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值