洛谷 P2486 [SDOI2011]染色
题目描述
输入输出格式
输入格式:
输出格式:
对于每个询问操作,输出一行答案。
输入输出样例
输入样例#1:
6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q 3 5 C 5 1 2 Q 3 5
输出样例#1:
3 1 2
说明
树链剖分。
#include<iostream> #include<cstdio> #include<cstring> #include<vector> const int N=100001; using namespace std; vector<int>vec[N]; int n,m,num,tot,colure[N]; int deep[N],size[N],dad[N],top[N],id[N]; struct nond{ int l,r,flag; int l_colure,r_colure,sum; }tree[N*2]; int dfs(int x){ size[x]=1; deep[x]=deep[dad[x]]+1; for(int i=0;i<vec[x].size();i++){ if(vec[x][i]!=dad[x]){ dad[vec[x][i]]=x; dfs(vec[x][i]); size[x]+=size[vec[x][i]]; } } } int dfs1(int x){ int t=0;num++; id[x]=num;//记录dfs序 if(!top[x]) top[x]=x; for(int i=0;i<vec[x].size();i++) if(vec[x][i]!=dad[x]&&size[vec[x][i]]>size[t]) t=vec[x][i]; if(t){ top[t]=top[x]; dfs1(t); } for(int i=0;i<vec[x].size();i++) if(vec[x][i]!=dad[x]&&vec[x][i]!=t) dfs1(vec[x][i]); } void up(int now){ int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2;//线段树,所以乘2,切记!!切记!! tree[now].sum=tree[l].sum+tree[r].sum-(tree[r].l_colure==tree[l].r_colure); tree[now].l_colure=tree[l].l_colure; tree[now].r_colure=tree[r].r_colure; } void build(int l,int r){ tot++; tree[tot].l=l; tree[tot].r=r; int y=tot; if(tree[tot].l==tree[tot].r) return ; int mid=(tree[tot].l+tree[tot].r)/2; build(l,mid); build(mid+1,r); up(y); } void change(int now,int t,int x){ if(tree[now].l==tree[now].r){ tree[now].l_colure=tree[now].r_colure=tree[now].flag=x; tree[now].sum=1; return; } int mid=(tree[now].l+tree[now].r)/2; int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2; if(t<=mid) change(l,t,x); else if(t>mid) change(r,t,x); up(now); } void down(int now){ if(tree[now].l==tree[now].r) return; int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2; tree[l].l_colure=tree[r].l_colure=tree[l].r_colure=tree[r].r_colure=tree[l].flag=tree[r].flag=tree[now].flag; tree[l].sum=tree[r].sum=1; tree[now].flag=0; } void change_many(int now,int pol,int por,int a){ if(tree[now].l==pol&&tree[now].r==por){ tree[now].flag=tree[now].l_colure=tree[now].r_colure=a; tree[now].sum=1; return; } if(tree[now].flag) down(now); int mid=(tree[now].l+tree[now].r)/2; int l=now+1,r=now+(tree[now+1].r-tree[now].l+1)*2; if(por<=mid) change_many(l,pol,por,a); else if(pol>mid) change_many(r,pol,por,a); else{ change_many(l,pol,mid,a); change_many(r,mid+1,por,a); } up(now); } int change_ans(int u,int v,int a){ while(top[u]!=top[v]){ if(deep[top[u]]<deep[top[v]]) swap(u,v); change_many(1,id[top[u]],id[u],a); u=dad[top[u]]; } if(id[u]>id[v]) swap(u,v); change_many(1,id[u],id[v],a); } int query(int now,int t){ if(tree[now].l==tree[now].r) return tree[now].flag; if(tree[now].flag) down(now); int mid=(tree[now].l+tree[now].r)/2; int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2; if(t<=mid) query(l,t); else query(r,t); } int query_many(int now,int pol,int por){ if(tree[now].l==pol&&tree[now].r==por){ return tree[now].sum; } if(tree[now].flag) down(now); int mid=(tree[now].l+tree[now].r)/2; int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2; if(por<=mid) return query_many(l,pol,por); else if(pol>mid) return query_many(r,pol,por); else{ int t=query_many(l,pol,mid)+query_many(r,mid+1,por); if(tree[l].r_colure==tree[r].l_colure) t--; return t; } } void query_ans(int u,int v){ int ans=0; while(top[u]!=top[v]){ if(deep[top[u]]<deep[top[v]]) swap(u,v); ans+=query_many(1,id[top[u]],id[u]); if(query(1,id[dad[top[u]]])==query(1,id[top[u]])) ans--; u=dad[top[u]]; } if(id[u]>id[v]) swap(u,v); ans+=query_many(1,id[u],id[v]); cout<<ans<<endl; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&colure[i]); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); vec[x].push_back(y); vec[y].push_back(x); } dfs(1); dfs1(1); build(1,n); for(int i=1;i<=n;i++) change(1,id[i],colure[i]); char ch;int a,b,c; for(int i=1;i<=m;i++){ cin>>ch; if(ch=='C'){ scanf("%d%d%d",&a,&b,&c); change_ans(a,b,c); } else{ scanf("%d%d",&a,&b); query_ans(a,b); } } return 0; }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。