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