BZOJ 2243: [SDOI2011]染色 [树链剖分+细节]【数据结构】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 Time Limit: 20 Sec Memory Limit: 512 MB 给定一棵有n个节点的无根树和m个操作,操作有2类: 第一行包含2个整数n和m,分别表示节点数和操作数; 对于每个询问操作,输出一行答案。 6 5 Sample Output 3 HINT 数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0,10^9]之间。 Source 第一轮day1 ———————————————————————————————————————————————— 在树上两点间的路上进行修改 那么就是树链剖分, 注意在维护的时候线段树上的每个点要多维护一个最左边和最右边的颜色。 然后就是注意颜色可能为0 附本题代码 ———————————————————————————————————————— #include <bits/stdc++.h>
using namespace std;
const int N = 1e5+7;
/***************************************/
int n,m;
int c[N];
vector<int >G[N];
int fa[N],sz[N],son[N],dep[N];
int dfs1(int u,int f,int d){
fa[u]=f,sz[u]=1,son[u]=0,dep[u]=d;
int gz = G[u].size();
for(int to,i=0;i<gz;i++){
to = G[u][i];
if(to==f) continue;
dfs1(to,u,d+1);
sz[u]+=sz[to];
if(sz[son[u]]<sz[to]) son[u]=to;
}
}
int top[N],tree[N],pre[N],cnt;
int dfs2(int u,int tp){
top[u]=tp,tree[u]=++cnt,pre[tree[u]]=u;
if(son[u]) dfs2(son[u],tp);
int gz = G[u].size();
for(int to,i=0;i<gz;i++){
to = G[u][i];
if(to==fa[u]||to==son[u])continue;
dfs2(to,to);
}
}
int sum[N<<2],lazy[N<<2],lc[N<<2],rc[N<<2];
void pushup(int rt){
sum[rt] = sum[rt<<1]+sum[rt<<1|1]-(rc[rt<<1] == lc[rt<<1|1]);
lc[rt]=lc[rt<<1],rc[rt]=rc[rt<<1|1];
}
void pushdown(int rt){
if(lazy[rt]!=-1){
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
sum [rt<<1] = sum [rt<<1|1] = 1;
lc[rt<<1] = rc[rt<<1] = lazy[rt];
lc[rt<<1|1] = rc[rt<<1|1] = lazy[rt];
lazy[rt]=-1;
}
}
void build(int rt,int l,int r){
if(l==r){
sum[rt]=1,rc[rt]=lc[rt]=c[pre[l]];
return ;
}
int m = (r+l)>>1;
build(rt<<1,l,m);
build(rt<<1|1,m+1,r);
pushup(rt);
}
void update(int rt,int r,int L,int R,int clr){
if(L<=l&&r<=R){
rc[rt]=lc[rt]=lazy[rt]=clr;
sum[rt] = 1;
return ;
}
pushdown(rt);
int m = (r+l)>>1;
if(L<=m) update(rt<<1,m,L,R,clr);
if(R> m) update(rt<<1|1,r,clr);
pushup(rt);
return ;
}
int query(int rt,int R){
if(L>R) return 0;
if(L<=l&&r<=R) return sum[rt];
pushdown(rt);
int ans = 0,m = (r+l)>>1;
if(R<=m) ans = query(rt<<1,R);
else if(L>m) ans = query(rt<<1|1,R);
else ans = query(rt<<1,R)+
query(rt<<1|1,R)-
(rc[rt<<1]==lc[rt<<1|1]);
pushup(rt);
return ans;
}
int query_color(int rt,int pos){
if(l==r) return lc[rt];
pushdown(rt);
int m = (r+l)>>1,ans;
if(pos<=m) ans = query_color(rt<<1,pos);
else ans = query_color(rt<<1|1,pos);
pushup(rt);
return ans;
}
void init(){
cnt = 0;
for(int i=1;i<=n;i++)G[i].clear();
memset(sum,0,sizeof(sum));
memset(lazy,-1,sizeof(lazy));
};
void brush(int x,int y,int clr){
int fx = top[x],fy = top[y];
while(fx!=fy){
if(dep[fx]<dep[fy]) swap(fx,fy),swap(x,y);
update(1,1,n,tree[fx],tree[x],clr);
x = fa[fx],fx = top[x];
}
if(tree[x]>tree[y]) swap(x,y);
update(1,tree[y],clr);
return ;
}
void solve(int x,int y){
int fx = top[x],fy = top[y];
int ans = 0;
while(fx!=fy){
if(dep[fx]<dep[fy]) swap(fx,y);
ans += query(1,tree[x]);
if(query_color(1,tree[fa[fx]]) == query_color(1,tree[fx])) ans--;
x = fa[fx],y);
ans += query(1,tree[y]);
printf("%dn",ans);
return ;
}
int main(){
while(~scanf("%d%d",&n,&m)){
init();
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
for(int i=2,v;i<=n;i++){
scanf("%d %d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs1(1,1);
dfs2(1,1);
build(1,n);
int l,x;
char a[10];
while(m--){
scanf("%s",a);
scanf("%d %d",&l,&r);
if(a[0]=='C'){
scanf("%d",&x);
brush(l,x);
}
else solve(l,r);
}
}
return 0;
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |