zoukankan      html  css  js  c++  java
  • BZOJ 2243 [SDOI2011]染色

    一道树剖的裸题。

    简单的线段树区间合并,比起什么堵塞的交通(心理阴影)。

    主要是注意细节,考场上就是注意对拍吧。

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    typedef long long LL;
    const int maxn=100005;
    using namespace std;
    int n,m,v[maxn],tp;
    
    int ecnt,nxt[maxn*2],to[maxn*2],fir[maxn];
    
    void add(int u,int v) {
        nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
        nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
    }
    
    int f[maxn],R[maxn],sz[maxn],tid[maxn],ftid[maxn],tot,top[maxn];
    int sg[maxn<<2],lz[maxn<<2],ll[maxn<<2],rr[maxn<<2];
    
    #define lc x<<1
    #define rc x<<1|1
    #define mid ((l+r)>>1)
    
    void down(int x,int l_len,int r_len) {
        if(lz[x]==-1) return;
        if(lc) { sg[lc]=1; ll[lc]=rr[lc]=lz[x]; lz[lc]=lz[x]; }
        if(rc) { sg[rc]=1; ll[rc]=rr[rc]=lz[x]; lz[rc]=lz[x]; }
        lz[x]=-1;
    }
    
    void change(int x,int l,int r,int ql,int qr,int v) {
         if(l>=ql&&r<=qr) { sg[x]=1; ll[x]=rr[x]=v; lz[x]=v; return;}
         down(x,mid-l+1,r-mid);
         if(ql<=mid) change(lc,l,mid,ql,qr,v);
         if(qr>mid) change(rc,mid+1,r,ql,qr,v);
         sg[x]=sg[lc]+sg[rc];
         ll[x]=ll[lc]; rr[x]=rr[rc];
         if(ll[rc]!=-1&&rr[lc]==ll[rc]) sg[x]--;
    }
    
    int qry(int x,int l,int r,int ql,int qr,int &wl,int &wr) {
        if(l>=ql&&r<=qr) {wl=ll[x]; wr=rr[x]; return sg[x];}
        down(x,mid-l+1,r-mid);
        if(qr<=mid) return qry(lc,l,mid,ql,qr,wl,wr);
        if(ql>mid) return qry(rc,mid+1,r,ql,qr,wl,wr);
        int res=qry(lc,l,mid,ql,qr,wl,tp)+qry(rc,mid+1,r,ql,qr,tp,wr);
        if(rr[lc]==ll[rc]) res--;
        return res;
    }
    
    void schange(int l,int r,int v) {
        while(top[l]!=top[r]) {
            if(R[top[l]]<R[top[r]]) swap(l,r);
            change(1,1,n,tid[top[l]],tid[l],v);
            l=f[top[l]];
        }
        if(tid[l]>tid[r]) swap(l,r);
        change(1,1,n,tid[l],tid[r],v);
    }
    
    int sqry(int l,int r) {
        int res=0,ls=-1,lx=-1,rs=-1,rx=-1,wl=-1,wr=-1,pre;
        while(top[l]!=top[r]) {
            if(R[top[l]]<R[top[r]]) swap(l,r),swap(lx,rx),swap(ls,rs);
            pre=ls;
            res+=qry(1,1,n,tid[top[l]],tid[l],ls,lx);
            if(pre==lx) res--; 
            l=f[top[l]];
        }
        if(tid[l]>tid[r]) swap(l,r),swap(ls,rs);
        res+=qry(1,1,n,tid[l],tid[r],wl,wr);
        if(wl!=-1&&wl==ls) res--; if(wr!=-1&&wr==rs)res--;
        return res;
    }
    
    void dfs(int x,int fa) {
        sz[x]=1; f[x]=fa; R[x]=R[fa]+1;
        for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa){
            dfs(to[i],x);
            sz[x]+=sz[to[i]];
        }
    }
    
    void DFS(int x,int p) {
        tid[x]=++tot;
        ftid[tot]=x;
        change(1,1,n,tot,tot,v[x]);
        top[x]=p;
        int mson=0;
        for(int i=fir[x];i;i=nxt[i]) if(to[i]!=f[x]) {
            if(!mson||sz[mson]<sz[to[i]]) mson=to[i];
        }
        if(!mson) return;
        DFS(mson,p);
        for(int i=fir[x];i;i=nxt[i]) if(to[i]!=f[x]&&to[i]!=mson) {
            DFS(to[i],to[i]);
        }
    }
    
    char op[10];
    int x,y;
    
    int main()
    {
        memset(lz,-1,sizeof(lz));
        memset(ll,-1,sizeof(ll));
        memset(rr,-1,sizeof(rr));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&v[i]);
        for(int i=1;i<n;i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        dfs(1,0);
        DFS(1,1);
        while(m--) {
            scanf("%s%d%d",op,&x,&y);
            if(op[0]=='C') {
                int z;
                scanf("%d",&z);
                schange(x,y,z);
            }
            else {
                printf("%d
    ",sqry(x,y));
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    在C++里while语句的一个妙用
    看书——我和村上作品
    Linux下使用QQ和查看QQ空间
    Redflag 6.0 Linux下装 nvidia fx5200显卡驱动
    唇伤
    看书——我和村上作品
    Firefox 3 查看QQ空间的问题——只能开8位以下QQ的空间
    codeforces 315 B.Sereja and Array
    codeforces 285C Building Permutation
    省赛总结
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7603860.html
Copyright © 2011-2022 走看看