BZOJ 2243 [SDOI2011]染色

Posted Achen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",sqry(x,y));
        }
    }
    return 0;
}
View Code

 

以上是关于BZOJ 2243 [SDOI2011]染色的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ2243][SDOI2011]染色

BZOJ2243: [SDOI2011]染色

BZOJ2243: [SDOI2011]染色

bzoj 2243: [SDOI2011]染色

BZOJ2243: [SDOI2011]染色

BZOJ 2243 SDOI 2011染色