bzoj 2243: [SDOI2011]染色 树链剖分+线段树

来源:互联网 发布:apache storm 决策树 编辑:程序博客网 时间:2024/05/09 10:11

题意:给出一棵树,每个节点有一个初始颜色。要求资瓷两个操作:

Q u v求u到v的路径上的颜色段的数量

C u v w把u到v的路径上的节点颜色都改为w


分析:一次AC的感觉真好

一眼看去就造是树剖啦

线段树每个节点维护三个值:该区间的颜色段数量、最左边节点颜色和最右边节点颜色

修改操作不多说

对于询问操作,在查找完每条重链后若该重链的顶点w和w的父节点的颜色一样则ans--


代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#define inf 0x7fffffff#define N 100005#define M 200005using namespace std;int n,m,color[N],cnt,fa[N],top[N],dep[N],size[N],pos[N],sz,last[N];struct data{int to,next;}e[M];struct tree{int l,r,sum,lc,rc,lazy;}t[300005];void insert(int u,int v){e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;}void init(){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++)scanf("%d",&color[i]);for (int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);insert(u,v);}}void dfs1(int x){size[x]=1;for (int i=last[x];i;i=e[i].next){if (e[i].to==fa[x]) continue;fa[e[i].to]=x;dep[e[i].to]=dep[x]+1;dfs1(e[i].to);size[x]+=size[e[i].to];}}void dfs2(int x,int chain){int k=0;sz++;top[x]=chain;pos[x]=sz;for (int i=last[x];i;i=e[i].next)if (e[i].to!=fa[x]&&size[e[i].to]>size[k]) k=e[i].to;if (k==0) return;dfs2(k,chain);for (int i=last[x];i;i=e[i].next)if (e[i].to!=fa[x]&&e[i].to!=k) dfs2(e[i].to,e[i].to);}void build(int d,int l,int r){t[d].l=l;t[d].r=r;if (l==r) return;int mid=(l+r)/2;build(d*2,l,mid);build(d*2+1,mid+1,r);}void pushlazy(int d){if (t[d].lazy==0||t[d].l==t[d].r) return;int w=t[d].lazy;t[d].lazy=0;t[d*2].sum=t[d*2+1].sum=1;t[d*2].lc=t[d*2].rc=t[d*2+1].lc=t[d*2+1].rc=t[d*2].lazy=t[d*2+1].lazy=w;}void queryC(int d,int x,int y,int z){if (t[d].l==x&&t[d].r==y){t[d].sum=1;t[d].lc=t[d].rc=t[d].lazy=z;return;}pushlazy(d);int mid=(t[d].l+t[d].r)/2;if (y<=mid) queryC(d*2,x,y,z);else if (x>mid) queryC(d*2+1,x,y,z);else {queryC(d*2,x,mid,z);queryC(d*2+1,mid+1,y,z);}t[d].lc=t[d*2].lc;t[d].rc=t[d*2+1].rc;t[d].sum=t[d*2].sum+t[d*2+1].sum;if (t[d*2].rc==t[d*2+1].lc) t[d].sum--;}void solveC(int x,int y,int z){while (top[x]!=top[y]){if (dep[top[x]]<dep[top[y]]) swap(x,y);queryC(1,pos[top[x]],pos[x],z);x=fa[top[x]];}if (dep[x]>dep[y]) swap(x,y);queryC(1,pos[x],pos[y],z);}int queryQ(int d,int x,int y){pushlazy(d);if (t[d].l==x&&t[d].r==y) return t[d].sum;int mid=(t[d].l+t[d].r)/2;if (y<=mid) return queryQ(d*2,x,y);else if (x>mid) return queryQ(d*2+1,x,y);else {int sum=queryQ(d*2,x,mid)+queryQ(d*2+1,mid+1,y);if (t[d*2].rc==t[d*2+1].lc) sum--;return sum;}}int find(int d,int x){pushlazy(d);if (t[d].sum==1) return t[d].lc;int mid=(t[d].l+t[d].r)/2;if (x<=mid) return find(d*2,x);else return find(d*2+1,x);}int solveQ(int x,int y){int sum=0;while (top[x]!=top[y]){if (dep[top[x]]<dep[top[y]]) swap(x,y);sum+=queryQ(1,pos[top[x]],pos[x]);if (find(1,pos[top[x]])==find(1,pos[fa[top[x]]])) sum--;x=fa[top[x]];}if (dep[x]>dep[y]) swap(x,y);sum+=queryQ(1,pos[x],pos[y]);return sum;}void solve(){build(1,1,n);char ch[2];for (int i=1;i<=n;i++)queryC(1,pos[i],pos[i],color[i]+1);for (int i=1;i<=m;i++){scanf("%s",ch);if (ch[0]=='C'){int x,y,z;scanf("%d%d%d",&x,&y,&z);solveC(x,y,z+1);}else{int x,y;scanf("%d%d",&x,&y);printf("%d\n",solveQ(x,y));}}}int main(){init();dfs1(1);dfs2(1,1);solve();}


0 0
原创粉丝点击