题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243
题意:
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如"112221"由3段组成:"11"、"222"和"1"。
请你写一个程序依次完成这m个操作。
题解:
树剖。
线段树上维护区间颜色段,每个节点:
dat[]:当前区间的颜色段数量
st[]:修改标记
lc[] and rc[]:当前区间的最左端和最右端颜色
lson[] and rson[]:左右儿子编号
线段树部分见NOI 2007 项链工厂。
树剖query中,每次a = par[tp[a]]往上跳之前,先判断getcol(dfsx[tp[a]]) == getcol(dfsx[par[tp[a]]])
如果相等,上下两端合并,sum--。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define MAX_N 1000005 6 7 using namespace std; 8 9 int n,m; 10 int tot=0; 11 int cnt=0; 12 int c[MAX_N]; 13 int dat[MAX_N]; 14 int st[MAX_N]; 15 int lc[MAX_N]; 16 int rc[MAX_N]; 17 int lson[MAX_N]; 18 int rson[MAX_N]; 19 int par[MAX_N]; 20 int dep[MAX_N]; 21 int siz[MAX_N]; 22 int tp[MAX_N]; 23 int son[MAX_N]; 24 int dfsx[MAX_N]; 25 int idx[MAX_N]; 26 vector<int> edge[MAX_N]; 27 28 void read() 29 { 30 scanf("%d%d",&n,&m); 31 for(int i=1;i<=n;i++) 32 { 33 scanf("%d",&c[i]); 34 } 35 int a,b; 36 for(int i=1;i<n;i++) 37 { 38 scanf("%d%d",&a,&b); 39 edge[a].push_back(b); 40 edge[b].push_back(a); 41 } 42 } 43 44 void push_down(int now) 45 { 46 if(st[now]!=-1) 47 { 48 dat[lson[now]]=dat[rson[now]]=1; 49 st[lson[now]]=st[rson[now]]=st[now]; 50 lc[lson[now]]=rc[lson[now]]=lc[rson[now]]=rc[rson[now]]=st[now]; 51 st[now]=-1; 52 } 53 } 54 55 void push_up(int now) 56 { 57 dat[now]=0; 58 lc[now]=lc[lson[now]]; 59 rc[now]=rc[rson[now]]; 60 if(lson[now]) dat[now]+=dat[lson[now]]; 61 if(rson[now]) dat[now]+=dat[rson[now]]; 62 if(lson[now] && rson[now] && rc[lson[now]]==lc[rson[now]]) dat[now]--; 63 } 64 65 int build(int l,int r) 66 { 67 int rt=++tot; 68 dat[rt]=1; 69 st[rt]=-1; 70 lc[rt]=c[idx[l]]; 71 rc[rt]=c[idx[r]]; 72 lson[rt]=rson[rt]=0; 73 if(l<r) 74 { 75 int mid=(l+r)>>1; 76 lson[rt]=build(l,mid); 77 rson[rt]=build(mid+1,r); 78 push_up(rt); 79 } 80 return rt; 81 } 82 83 void update(int a,int b,int k,int l,int r,int x) 84 { 85 if(a<=l && r<=b) 86 { 87 dat[k]=1; 88 st[k]=lc[k]=rc[k]=x; 89 return; 90 } 91 if(r<a || b<l) return; 92 push_down(k); 93 int mid=(l+r)>>1; 94 update(a,b,lson[k],l,mid,x); 95 update(a,b,rson[k],mid+1,r,x); 96 push_up(k); 97 } 98 99 int query(int a,int b,int k,int l,int r) 100 { 101 if(a<=l && r<=b) return dat[k]; 102 if(r<a || b<l) return 0; 103 push_down(k); 104 int mid=(l+r)>>1; 105 int ans=0; 106 if(a<=mid) ans+=query(a,b,lson[k],l,mid); 107 if(b>mid) ans+=query(a,b,rson[k],mid+1,r); 108 if(a<=mid && b>mid && rc[lson[k]]==lc[rson[k]]) ans--; 109 return ans; 110 } 111 112 int getcol(int p,int k,int l,int r) 113 { 114 if(l==r) return lc[k]; 115 push_down(k); 116 int mid=(l+r)>>1; 117 if(p<=mid) return getcol(p,lson[k],l,mid); 118 else return getcol(p,rson[k],mid+1,r); 119 } 120 121 void dfs1(int now,int p,int d) 122 { 123 par[now]=p; 124 dep[now]=d; 125 siz[now]=1; 126 for(int i=0;i<edge[now].size();i++) 127 { 128 int temp=edge[now][i]; 129 if(temp!=p) 130 { 131 dfs1(temp,now,d+1); 132 siz[now]+=siz[temp]; 133 } 134 } 135 } 136 137 void dfs2(int now,int anc) 138 { 139 tp[now]=anc; 140 son[now]=-1; 141 cnt++; 142 idx[cnt]=now; 143 dfsx[now]=cnt; 144 for(int i=0;i<edge[now].size();i++) 145 { 146 int temp=edge[now][i]; 147 if((son[now]==-1 || siz[temp]>siz[son[now]]) && temp!=par[now]) 148 { 149 son[now]=temp; 150 } 151 } 152 if(son[now]!=-1) dfs2(son[now],anc); 153 for(int i=0;i<edge[now].size();i++) 154 { 155 int temp=edge[now][i]; 156 if(temp!=par[now] && temp!=son[now]) dfs2(temp,temp); 157 } 158 } 159 160 void update_chain(int a,int b,int x) 161 { 162 while(tp[a]!=tp[b]) 163 { 164 if(dep[tp[a]]<dep[tp[b]]) swap(a,b); 165 update(dfsx[tp[a]],dfsx[a],1,1,n,x); 166 a=par[tp[a]]; 167 } 168 if(dep[a]<dep[b]) swap(a,b); 169 update(dfsx[b],dfsx[a],1,1,n,x); 170 } 171 172 int query_chain(int a,int b) 173 { 174 int sum=0; 175 while(tp[a]!=tp[b]) 176 { 177 if(dep[tp[a]]<dep[tp[b]]) swap(a,b); 178 sum+=query(dfsx[tp[a]],dfsx[a],1,1,n); 179 if(getcol(dfsx[tp[a]],1,1,n)==getcol(dfsx[par[tp[a]]],1,1,n)) sum--; 180 a=par[tp[a]]; 181 } 182 if(dep[a]<dep[b]) swap(a,b); 183 sum+=query(dfsx[b],dfsx[a],1,1,n); 184 return sum; 185 } 186 187 void work() 188 { 189 dfs1(1,-1,0); 190 dfs2(1,1); 191 build(1,n); 192 char s[16]; 193 int a,b,c; 194 while(m--) 195 { 196 scanf("%s",s); 197 if(s[0]=='Q') 198 { 199 scanf("%d%d",&a,&b); 200 printf("%d ",query_chain(a,b)); 201 } 202 else 203 { 204 scanf("%d%d%d",&a,&b,&c); 205 update_chain(a,b,c); 206 } 207 } 208 } 209 210 int main() 211 { 212 read(); 213 work(); 214 }