Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。
Sample Input
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 5Sample Output
3
1
2HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
【分析】
还是树链剖分,主要是线段树那里,要记录最左边的颜色和最右边的颜色,合并的时候看看中间相接部分颜色是否相同,如果相同ans-1.
询问的时候是要重链、轻边的跳的,也是要记录左右的颜色,判断颜色是否相同。
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 100010 8 9 struct node 10 { 11 int x,y,next; 12 }t[2*Maxn];int len=0; 13 14 int c[Maxn],fa[Maxn],size[Maxn],first[Maxn],dep[Maxn]; 15 int top[Maxn],w[Maxn],son[Maxn]; 16 int wl=0; 17 18 void ins(int x,int y) 19 { 20 t[++len].x=x;t[len].y=y; 21 t[len].next=first[x];first[x]=len; 22 } 23 24 struct nnode 25 { 26 int l,r,lc,rc,cl,cr,sum,lazy; 27 }tr[2*Maxn];int tl=0; 28 29 void dfs1(int x,int f) 30 { 31 dep[x]=dep[f]+1; 32 size[x]=1;fa[x]=f;son[x]=0; 33 for(int i=first[x];i;i=t[i].next) if(t[i].y!=f) 34 { 35 dfs1(t[i].y,x); 36 size[x]+=size[t[i].y]; 37 if(size[t[i].y]>size[son[x]]) son[x]=t[i].y; 38 } 39 } 40 41 void dfs2(int x,int tp) 42 { 43 top[x]=tp;w[x]=++wl; 44 if(size[x]!=1) dfs2(son[x],tp); 45 for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x]) 46 { 47 dfs2(t[i].y,t[i].y); 48 } 49 } 50 51 int build(int l,int r) 52 { 53 int x=++tl; 54 tr[x].l=l;tr[x].r=r;tr[x].lazy=-1;tr[x].sum=0; 55 if(l!=r) 56 { 57 int mid=(l+r)>>1; 58 tr[x].lc=build(l,mid); 59 tr[x].rc=build(mid+1,r); 60 } 61 return x; 62 } 63 64 void upd(int x) 65 { 66 if(tr[x].lazy==-1) return; 67 tr[x].sum=1;tr[x].cl=tr[x].cr=tr[x].lazy; 68 if(tr[x].l!=tr[x].r) 69 { 70 tr[tr[x].lc].lazy=tr[x].lazy; 71 tr[tr[x].rc].lazy=tr[x].lazy; 72 } 73 tr[x].lazy=-1; 74 } 75 76 void change(int x,int l,int r,int y) 77 { 78 if(tr[x].l==l&&tr[x].r==r) 79 { 80 tr[x].lazy=y; 81 return; 82 } 83 upd(x); 84 int mid=(tr[x].l+tr[x].r)>>1; 85 if(r<=mid) change(tr[x].lc,l,r,y); 86 else if(l>mid) change(tr[x].rc,l,r,y); 87 else 88 { 89 change(tr[x].lc,l,mid,y); 90 change(tr[x].rc,mid+1,r,y); 91 } 92 upd(tr[x].lc);upd(tr[x].rc); 93 tr[x].cl=tr[tr[x].lc].cl; 94 tr[x].cr=tr[tr[x].rc].cr; 95 tr[x].sum=tr[tr[x].lc].sum+tr[tr[x].rc].sum; 96 if(tr[tr[x].lc].cr==tr[tr[x].rc].cl) tr[x].sum--; 97 } 98 99 void ffind(int x,int y,int z) 100 { 101 int f1=top[x],f2=top[y]; 102 while(f1!=f2) 103 { 104 if(dep[f1]<dep[f2]) 105 { 106 swap(f1,f2); 107 swap(x,y); 108 } 109 change(1,w[f1],w[x],z); 110 x=fa[f1]; 111 f1=top[x]; 112 } 113 if(dep[x]<dep[y]) swap(x,y); 114 change(1,w[y],w[x],z); 115 } 116 117 int q1,q2,a1,a2; 118 int queryt(int x,int l,int r) 119 { 120 upd(x); 121 if(tr[x].l==l&&tr[x].r==r) 122 { 123 if(q1==tr[x].l) a1=tr[x].cl; 124 if(q2==tr[x].r) a2=tr[x].cr; 125 return tr[x].sum; 126 } 127 int mid=(tr[x].l+tr[x].r)>>1; 128 if(r<=mid) return queryt(tr[x].lc,l,r); 129 if(l>mid) return queryt(tr[x].rc,l,r); 130 int ans=queryt(tr[x].lc,l,mid)+queryt(tr[x].rc,mid+1,r); 131 if(tr[tr[x].lc].cr==tr[tr[x].rc].cl) ans--; 132 return ans; 133 } 134 135 int query(int x,int y) 136 { 137 int cl=-1,cr=-1,f1=top[x],f2=top[y]; 138 int ans=0; 139 while(f1!=f2) 140 { 141 if(dep[f1]>=dep[f2]) 142 { 143 q1=w[f1];q2=w[x]; 144 ans+=queryt(1,w[f1],w[x]); 145 if(a2==cl) ans--; 146 cl=a1; 147 x=fa[f1];f1=top[x]; 148 } 149 else 150 { 151 q1=w[f2];q2=w[y]; 152 ans+=queryt(1,w[f2],w[y]); 153 if(a2==cr) ans--; 154 cr=a1; 155 y=fa[f2];f2=top[y]; 156 } 157 } 158 if(dep[x]<=dep[y]) 159 { 160 q1=w[x];q2=w[y]; 161 ans+=queryt(1,w[x],w[y]); 162 if(cl==a1) ans--; 163 if(cr==a2) ans--; 164 } 165 else 166 { 167 q1=w[y];q2=w[x]; 168 ans+=queryt(1,w[y],w[x]); 169 if(cr==a1) ans--; 170 if(cl==a2) ans--; 171 } 172 return ans; 173 } 174 175 int main() 176 { 177 int n,m; 178 scanf("%d%d",&n,&m); 179 for(int i=1;i<=n;i++) scanf("%d",&c[i]); 180 memset(first,0,sizeof(first)); 181 for(int i=1;i<n;i++) 182 { 183 int x,y; 184 scanf("%d%d",&x,&y); 185 ins(x,y);ins(y,x); 186 } 187 dfs1(1,0); 188 dfs2(1,1); 189 build(1,n); 190 for(int i=1;i<=n;i++) change(1,w[i],w[i],c[i]); 191 char s[10]; 192 while(m--) 193 { 194 scanf("%s",s); 195 if(s[0]=='Q') 196 { 197 int x,y; 198 scanf("%d%d",&x,&y); 199 printf("%d\n",query(x,y)); 200 } 201 else 202 { 203 int x,y,z; 204 scanf("%d%d%d",&x,&y,&z); 205 ffind(x,y,z); 206 } 207 } 208 return 0; 209 }
2016-05-12 16:34:01