SDOI 2011 染色

给定一棵有 n 个节点的无根树和 m 个操作,操作共两类。

将节点 a 到节点 b 路径上的所有节点都染上颜色;

询问节点 a 到节点 b 路径上的颜色段数量,连续相同颜色的认为是同一段,例如 112221 由三段组成:11 、 222、1。

请你写一个程序依次完成操作。

输入格式
第一行包括两个整数 n,m,表示节点数和操作数;

第二行包含 n 个正整数表示 n 个节点的初始颜色;

接下来若干行包含两个整数 x 和 y,表示 x 和 y 之间有一条无向边;

接下来若干行每行描述一个操作:

C a b c 表示这是一个染色操作,把节点 a 到节点 b 路径上所有点(包括 a 和 b)染上颜色;

Q a b 表示这是一个询问操作,把节点 a 到节点 b 路径上(包括 a 和 b)的颜色段数量。

输出格式
对于每个询问操作,输出一行询问结果。

样例
样例输入
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
样例输出
3
1
2
数据范围与提示
对于 100% 的数据,N,M≤10^5, 所有颜色 C 为整数且在 [0,10^9] 之间。

_____________________________________________________________________________________

树链剖分,需要维护

sum[]:表示段内的色段数

lc[]:表示左侧点的颜色

rc[]:表示右侧点的颜色

所以,

sum[cur]=sum[cur<<1]+sum[cur<<1|1]-(rc[cur<<1]==lc[cur<<1|1])

lc[cur]=lc[cur<<1]

rc[cur]=rc[cur<<1|1]

需要注意,树链之间两点的颜色是否相同。

———————————————————————————————————————————————

  1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1e5+10;
4 int n,m;
5 struct edge
6 {
7 int u,v,nxt;
8 }e[maxn<<1];
9 int head[maxn],js;
10 void addage(int u,int v)
11 {
12 e[++js].u=u;e[js].v=v;
13 e[js].nxt=head[u];head[u]=js;
14 }
15 int w[maxn];
16 int dep[maxn],fat[maxn],son[maxn],siz[maxn];
17 void dfs(int u,int fa)
18 {
19 dep[u]=dep[fa]+1;
20 fat[u]=fa;
21 siz[u]=1;
22 for(int i=head[u];i;i=e[i].nxt)
23 {
24 int v=e[i].v;
25 if(v==fa)continue;
26 dfs(v,u);
27 siz[u]+=siz[v];
28 if(!son[u] || siz[son[u]]<siz[v])son[u]=v;
29 }
30 }
31 int pos[maxn],fos[maxn],top[maxn],p;
32 void getpos(int u,int fa)
33 {
34 pos[u]=++p;
35 fos[p]=u;
36 top[u]=fa;
37 if(!son[u])return;
38 getpos(son[u],fa);
39 for(int i=head[u];i;i=e[i].nxt)
40 {
41 int v=e[i].v;
42 if(v!=fat[u] && v!=son[u])getpos(v,v);
43 }
44 }
45 int sum[maxn<<2],lc[maxn<<2],rc[maxn<<2],delt[maxn<<2];
46 void update(int cur)
47 {
48 lc[cur]=lc[cur<<1];
49 rc[cur]=rc[cur<<1|1];
50 sum[cur]=sum[cur<<1]+sum[cur<<1|1]-(rc[cur<<1]==lc[cur<<1|1]);
51 }
52 void build(int cur,int l,int r)
53 {
54 if(l==r)
55 {
56 lc[cur]=rc[cur]=w[fos[l]];
57 sum[cur]=1;
58 return;
59 }
60 int mid=(l+r)>>1;
61 build(cur<<1,l,mid);
62 build(cur<<1|1,mid+1,r);
63 update(cur);
64 }
65 void down(int cur)
66 {
67 sum[cur<<1]=sum[cur<<1|1]=1;
68 delt[cur<<1]=delt[cur<<1|1]=lc[cur<<1]=rc[cur<<1]=lc[cur<<1|1]=rc[cur<<1|1]=delt[cur];
69 delt[cur]=-1;
70 }
71 void modi(int cur,int l,int r,int ql,int qr,int x)
72 {
73 if(ql<=l && r<=qr)
74 {
75 sum[cur]=1;
76 delt[cur]=lc[cur]=rc[cur]=x;
77 return ;
78 }
79 int mid=(l+r)>>1;
80 if(delt[cur]!=-1)down(cur);
81 if(ql<=mid)modi(cur<<1,l,mid,ql,qr,x);
82 if(mid<qr)modi(cur<<1|1,mid+1,r,ql,qr,x);
83 update(cur);
84 }
85 void change(int u,int v,int x)
86 {
87 int tpu=top[u],tpv=top[v];
88 while(tpu!=tpv)
89 {
90 if(dep[tpu]<dep[tpv])
91 {
92 swap(u,v);swap(tpu,tpv);
93 }
94 modi(1,1,n,pos[tpu],pos[u],x);
95 u=fat[tpu];tpu=top[u];
96 }
97 if(dep[u]>dep[v])swap(u,v);
98 modi(1,1,n,pos[u],pos[v],x);
99 }
100 int query_c(int cur,int l,int r,int p)
101 {
102 if(l==r)return lc[cur];
103 int mid=(l+r)>>1;
104 if(delt[cur]!=-1)down(cur);
105 if(p<=mid)return query_c(cur<<1,l,mid,p);
106 else return query_c(cur<<1|1,mid+1,r,p);
107 }
108 int query(int cur,int l,int r,int ql,int qr)
109 {
110 if(ql<=l && r<=qr)return sum[cur];
111 int mid=(l+r)>>1,ans=0;
112 if(delt[cur]!=-1)down(cur);
113 if(ql<=mid)ans+=query(cur<<1,l,mid,ql,qr);
114 if(qr>mid)ans+=query(cur<<1|1,mid+1,r,ql,qr);
115 if(ql<=mid && mid<qr)ans-=rc[cur<<1]==lc[cur<<1|1];
116 return ans;
117 }
118 int ask(int u,int v)
119 {
120 int ans=0;
121 int clt,clp;
122 int tpu=top[u],tpv=top[v];
123 while(tpu!=tpv)
124 {
125 if(dep[tpu]<dep[tpv])
126 {
127 swap(u,v);swap(tpu,tpv);
128 }
129 clt=query_c(1,1,n,pos[tpu]);
130 clp=query_c(1,1,n,pos[fat[tpu]]);
131 ans+=query(1,1,n,pos[tpu],pos[u])-(clt==clp);
132 u=fat[tpu];tpu=top[u];
133 }
134 if(dep[u]>dep[v])swap(u,v);
135 ans+=query(1,1,n,pos[u],pos[v]);
136 return ans;
137 }
138 int main()
139 {
140 scanf("%d%d",&n,&m);
141 for(int i=1;i<=n;++i)scanf("%d",w+i);
142 for(int u,v,i=1;i<n;++i)
143 {
144 scanf("%d%d",&u,&v);
145 addage(u,v);addage(v,u);
146 }
147 dfs(1,0);
148 getpos(1,1);
149 memset(delt,-1,sizeof(delt));
150 build(1,1,n);
151 char s[3];
152 int a,b,c;
153 while(m--)
154 {
155 scanf("%s",s);
156 if(s[0]=='C')
157 {
158 scanf("%d%d%d",&a,&b,&c);
159 change(a,b,c);
160 }
161 else
162 {
163 scanf("%d%d",&a,&b);
164 printf("%d\n",ask(a,b));
165 }
166 }
167 return 0;
168 }

最新文章

  1. 设计模式之二:MVC
  2. python中保留两位小数
  3. PO/POJO/VO/BO/DAO/DTO
  4. rails第一次做项目
  5. JavaScript中var a=b=c=d的小发现
  6. bzoj2301(莫比乌斯反演+分块)
  7. ServerSuperIO 3.5版本的体系结构,以及未来规划的几点思考
  8. Git协作
  9. 异步获取CMD命令行输出内容
  10. 怎么查 ODBC Driver for SQL Server
  11. echart 3 数据密集时,断点不显示问题
  12. Chapter 3 Phenomenon——20
  13. 免费的协作和协同办公软件平台onlyoffice轻松部署
  14. Svn 提示错误:previous operation has not finished 解决方案
  15. python3之模板pycurl探测web服务质量
  16. AVR Programming Methods
  17. 第12章 GPIO输入-按键检测—零死角玩转STM32-F429系列
  18. [坑况]——webpack搭建前端环境踩过的坑啊
  19. ERP系统和MES系统的区别
  20. linux 块设备-整理(一)

热门文章

  1. Selenium多浏览器测试
  2. 一道java算法题
  3. IDEA 远程debug
  4. [LeetCode]42. Trapping Rain Water雨水填坑
  5. JDBC数据库删除
  6. Android ADB原理及常用命令
  7. 一个坑,bootstrap selectpicker 重置下拉列表时遇到的问题
  8. JAVA_基础IO流对象流(三)
  9. Servlet[JAX-RS Servlet]的Servlet.init()引发异常
  10. Nginx集成Naxsi防火墙