[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
说明
题解:
线段树+树链划分
先将树拆成链,在用线段树维护区间的答案
难点就是怎么维护,还有一个问题如下:
树上的路径可能有多条线段构成,就算维护了区间的答案,还要把那些线段合并
维护方法,lx表示当前线段的左边颜色,rx同理,合并线段时,如果lson的rx=rson的lx则sum-1
每次查询完路径的一个树链后,判断链的上端点和其父节点的颜色,若相同,则ans-1
修改用lazy标记就行
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct Node 7 { 8 int next,to; 9 }edge[200001]; 10 int head[100001],num,son[100001],size[100001],s[400001],lx[400001],rx[400001],pos[100001]; 11 int top[100001],fa[100001],dep[100001],tot,sgm[100001],color[100001],lazy[400001],n,m; 12 char get_op() 13 { 14 char ch=getchar(); 15 while (ch!='C'&&ch!='Q') ch=getchar(); 16 return ch; 17 } 18 void add(int u,int v) 19 { 20 num++; 21 edge[num].next=head[u]; 22 head[u]=num; 23 edge[num].to=v; 24 } 25 void dfs1(int u,int pa) 26 {int i; 27 size[u]=1; 28 dep[u]=dep[pa]+1; 29 fa[u]=pa; 30 for(int i=head[u]; i; i=edge[i].next) 31 { 32 int v=edge[i].to; 33 if(v==pa)continue; 34 dfs1(v,u); 35 size[u]+=size[v]; 36 if(size[v]>size[son[u]])son[u]=v; 37 } 38 } 39 void dfs2(int u,int pa,int tp) 40 {int i; 41 pos[u]=++tot; 42 sgm[tot]=u; 43 top[u]=tp; 44 if(son[u]) dfs2(son[u],u,tp); 45 for(int i=head[u]; i; i=edge[i].next) 46 { 47 int v=edge[i].to; 48 if(v==pa||v==son[u])continue; 49 dfs2(v,u,v); 50 } 51 } 52 void pushdown(int rt) 53 { 54 if (lazy[rt]!=-1) 55 { 56 lazy[rt*2]=lazy[rt]; 57 lazy[rt*2+1]=lazy[rt]; 58 lx[rt*2]=lx[rt*2+1]=rx[rt*2]=rx[rt*2+1]=lazy[rt]; 59 s[rt*2+1]=s[rt*2]=1; 60 lazy[rt]=-1; 61 } 62 } 63 void pushup(int rt) 64 { 65 lx[rt]=lx[rt*2]; 66 rx[rt]=rx[rt*2+1]; 67 s[rt]=s[rt*2]+s[rt*2+1]; 68 if (lx[rt*2+1]==rx[rt*2]) s[rt]--; 69 } 70 void build(int rt,int l,int r) 71 {lazy[rt]=-1; 72 if (l==r) 73 { 74 s[rt]=1; 75 lx[rt]=rx[rt]=color[sgm[l]]; 76 //cout<<sgm[l]<<' '<<l<<endl; 77 return; 78 } 79 int mid=(l+r)/2; 80 build(rt*2,l,mid); 81 build(rt*2+1,mid+1,r); 82 pushup(rt); 83 } 84 int query(int rt,int l,int r,int L,int R) 85 {int ans=0; 86 if (l==L&&r==R) 87 { 88 return s[rt]; 89 } 90 pushdown(rt); 91 int mid=(l+r)/2; 92 if (L>mid) return query(rt*2+1,mid+1,r,L,R); 93 else if (R<=mid) return query(rt*2,l,mid,L,R); 94 else 95 { 96 ans=query(rt*2,l,mid,L,mid)+query(rt*2+1,mid+1,r,mid+1,R); 97 if (lx[rt*2+1]==rx[rt*2]) ans--; 98 return ans; 99 } 100 } 101 void update(int rt,int l,int r,int L,int R,int d) 102 { 103 if (l==L&&r==R) 104 { 105 s[rt]=1; 106 lx[rt]=rx[rt]=d; 107 lazy[rt]=d; 108 return; 109 } 110 pushdown(rt); 111 int mid=(l+r)/2; 112 if(L>mid)update(rt*2+1,mid+1,r,L,R,d); 113 else if(R<=mid)update(rt*2,l,mid,L,R,d); 114 else update(rt*2,l,mid,L,mid,d),update(rt*2+1,mid+1,r,mid+1,R,d); 115 pushup(rt); 116 } 117 void change(int x,int y,int d) 118 { 119 while (top[x]!=top[y]) 120 { 121 if (dep[top[x]]<dep[top[y]]) swap(x,y); 122 update(1,1,tot,pos[top[x]],pos[x],d); 123 x=fa[top[x]]; 124 } 125 if (dep[x]>dep[y]) swap(x,y); 126 update(1,1,tot,pos[x],pos[y],d); 127 } 128 int query_color(int rt,int l,int r,int x) 129 { 130 if (l==r) 131 { 132 return lx[rt]; 133 } 134 pushdown(rt); 135 int mid=(l+r)/2; 136 if (x<=mid) return query_color(rt*2,l,mid,x); 137 else return query_color(rt*2+1,mid+1,r,x); 138 } 139 int ask(int x,int y) 140 { 141 int ans=0; 142 while (top[x]!=top[y]) 143 { 144 if (dep[top[x]]<dep[top[y]]) swap(x,y); 145 ans+=query(1,1,tot,pos[top[x]],pos[x]); 146 int p1=query_color(1,1,tot,pos[top[x]]); 147 int p2=query_color(1,1,tot,pos[fa[top[x]]]); 148 //cout<<x<<' '<<y<<' '<<ans<<endl; 149 x=fa[top[x]]; 150 if (p1==p2) ans--; 151 } 152 if (dep[x]>dep[y]) swap(x,y); 153 ans+=query(1,1,tot,pos[x],pos[y]); 154 if (ans==0) return 1; 155 return ans; 156 } 157 int main() 158 {int i,j,x,y,c; 159 char opt; 160 cin>>n>>m; 161 memset(lazy,-1,sizeof(lazy)); 162 for (i=1;i<=n;i++) 163 { 164 scanf("%d",&color[i]); 165 } 166 for (i=1;i<=n-1;i++) 167 { 168 scanf("%d%d",&x,&y); 169 add(x,y); 170 add(y,x); 171 } 172 dfs1(1,1); 173 dfs2(1,1,1); 174 build(1,1,tot); 175 for (i=1;i<=m;i++) 176 { 177 opt=get_op(); 178 if (opt=='Q') 179 { 180 scanf("%d%d",&x,&y); 181 printf("%d\n",ask(x,y)); 182 } 183 else 184 { 185 scanf("%d%d",&x,&y,&c); 186 change(x,y,c); 187 } 188 } 189 }