2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 11290 Solved: 4392
题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=2243
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 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
Sample Output
3
1
2
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
题解
这题也算是树链剖分的一种经典模型吧,线段树只要记录该区间最左端点的值,最右端点的值,以及该区间的段数和就可以了。
合并的话,考虑下中间交接部分就行。
树剖的时候每段之间再判断一下交界处即可。
打完才发现原来再洛谷做过一遍了,竟然没有印象了,不过莫名比上次快了两秒,这次总时间3秒,上次5秒。
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define N 200050 5 int n,m,w[N]; 6 struct Edge{int from,to,s;}edges[N<<1]; 7 int tot,last[N]; 8 struct Tree{int l,r,lazy,lb,rb,sum;}tr[N<<2]; 9 int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N]; 10 struct Query{int sum,lb,rb;}; 11 template<typename T>void read(T&x) 12 { 13 ll k=0; char c=getchar(); 14 x=0; 15 while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar(); 16 if (c==EOF)exit(0); 17 while(isdigit(c))x=x*10+c-'0',c=getchar(); 18 x=k?-x:x; 19 } 20 void read_char(char &c) 21 {while(!isalpha(c=getchar())&&c!=EOF);} 22 void AddEdge(int x,int y) 23 { 24 edges[++tot]=Edge{x,y,last[x]}; 25 last[x]=tot; 26 } 27 void push_up(int x) 28 { 29 Tree a=tr[x<<1],b=tr[x<<1|1]; 30 int len=tr[x].r-tr[x].l+1; 31 if (len>1) 32 { 33 tr[x].sum=a.sum+b.sum-(a.rb==b.lb); 34 tr[x].lb=a.lb; 35 tr[x].rb=b.rb; 36 } 37 else tr[x].sum=0; 38 if (tr[x].lazy!=-1) 39 {tr[x].sum=1;tr[x].lb=tr[x].rb=tr[x].lazy;} 40 } 41 void push_down(int x) 42 { 43 if (tr[x].lazy==-1)return; 44 tr[x<<1].lazy=tr[x].lazy; 45 tr[x<<1|1].lazy=tr[x].lazy; 46 push_up(x<<1); 47 push_up(x<<1|1); 48 tr[x].lazy=-1; 49 } 50 void bt(int x,int l,int r) 51 { 52 tr[x].l=l; tr[x].r=r; tr[x].lazy=-1; 53 if (l==r) 54 { 55 tr[x].lb=tr[x].rb=w[kth[l]]; 56 tr[x].sum=1; 57 return; 58 } 59 int mid=(l+r)>>1; 60 bt(x<<1,l,mid); 61 bt(x<<1|1,mid+1,r); 62 push_up(x); 63 } 64 void update(int x,int l,int r,int tt) 65 { 66 if (l<=tr[x].l&&tr[x].r<=r) 67 { 68 tr[x].lazy=tt; 69 push_up(x); 70 return; 71 } 72 int mid=(tr[x].l+tr[x].r)>>1; 73 push_down(x); 74 if (l<=mid)update(x<<1,l,r,tt); 75 if (mid<r)update(x<<1|1,l,r,tt); 76 push_up(x); 77 } 78 Query query(int x,int l,int r) 79 { 80 if (l<=tr[x].l&&tr[x].r<=r) 81 { 82 return Query{tr[x].sum,tr[x].lb,tr[x].rb}; 83 } 84 int mid=(tr[x].l+tr[x].r)>>1; 85 Query tp1={0,-1,-1},tp2={0,-1,-1},tp; 86 push_down(x); 87 if (l<=mid)tp1=query(x<<1,l,r); 88 if (mid<r)tp2=query(x<<1|1,l,r); 89 push_up(x); 90 tp.sum=tp1.sum+tp2.sum-(tp1.rb==tp2.lb); 91 tp.lb=tp1.lb==-1?tp2.lb:tp1.lb; 92 tp.rb=tp2.rb==-1?tp1.rb:tp2.rb; 93 return tp; 94 } 95 void dfs1(int x,int pre) 96 { 97 fa[x]=pre; 98 dp[x]=dp[pre]+1; 99 size[x]=1; 100 son[x]=0; 101 for(int i=last[x];i;i=edges[i].s) 102 { 103 Edge &e=edges[i]; 104 if (e.to==pre)continue; 105 dfs1(e.to,x); 106 size[x]+=size[e.to]; 107 if (size[e.to]>size[son[x]])son[x]=e.to; 108 } 109 } 110 void dfs2(int x,int y) 111 { 112 rk[x]=++cnt; 113 kth[cnt]=x; 114 top[x]=y; 115 if(son[x]==0)return; 116 dfs2(son[x],y); 117 for(int i=last[x];i;i=edges[i].s) 118 { 119 Edge &e=edges[i]; 120 if (e.to==fa[x]||e.to==son[x])continue; 121 dfs2(e.to,e.to); 122 } 123 } 124 void change(int x,int y,int tt) 125 { 126 int fx=top[x],fy=top[y]; 127 while(fx!=fy) 128 { 129 if(dp[fx]<dp[fy])swap(x,y),swap(fx,fy); 130 update(1,rk[fx],rk[x],tt); 131 x=fa[fx];fx=top[x]; 132 } 133 if (dp[x]<dp[y])swap(x,y); 134 update(1,rk[y],rk[x],tt); 135 } 136 int get_sum(int x,int y) 137 { 138 int fx=top[x],fy=top[y],lx=-1,ly=-1,ans=0; 139 Query tp; 140 while(fx!=fy) 141 { 142 if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy),swap(lx,ly); 143 tp=query(1,rk[fx],rk[x]); 144 ans+=tp.sum-(tp.rb==lx); 145 lx=tp.lb; x=fa[fx]; fx=top[x]; 146 } 147 if (dp[x]<dp[y])swap(x,y),swap(lx,ly); 148 tp=query(1,rk[y],rk[x]); 149 ans+=tp.sum-(tp.lb==ly)-(tp.rb==lx); 150 return ans; 151 } 152 int main() 153 { 154 #ifndef ONLINE_JUDGE 155 freopen("aa.in","r",stdin); 156 #endif 157 read(n); read(m); 158 for(int i=1;i<=n;i++)read(w[i]); 159 for(int i=1;i<=n-1;i++) 160 { 161 int x,y; 162 read(x); read(y); 163 AddEdge(x,y); 164 AddEdge(y,x); 165 } 166 dfs1(1,0); 167 dfs2(1,1); 168 bt(1,1,n); 169 for(int i=1;i<=m;i++) 170 { 171 char id; int x,y,tt; 172 read_char(id); read(x); read(y); 173 if(id=='C') 174 { 175 read(tt); 176 change(x,y,tt); 177 } 178 if (id=='Q')printf("%d ",get_sum(x,y)); 179 } 180 }