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 }

LOJ10141染色的更多相关文章

  1. bzoj2243树链剖分+染色段数

    终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...

  2. 51nod 算法马拉松18 A 染色问题

    染色问题 基准时间限制:1 秒 空间限制:10240 KB 分值: 40 一个n(3<=n<=100)个点的完全图,现在给出n,要求将每条边都染上一种颜色k(1<=k<=n), ...

  3. BZOJ 2243: [SDOI2011]染色 [树链剖分]

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6651  Solved: 2432[Submit][Status ...

  4. NOIP2008双栈排序[二分图染色|栈|DP]

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  5. 洛谷P1330封锁阳光大学[二分图染色]

    题目描述 曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街.河蟹看到欢快的曹,感到不爽.河蟹决定封锁阳光大学,不让曹刷街. 阳光大学的校园是一张由N个点构成的无向图,N个点之间由M ...

  6. POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Acce ...

  7. NOIP2010关押罪犯[并查集|二分答案+二分图染色 | 种类并查集]

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示 ...

  8. POJ1112 Team Them Up![二分图染色 补图 01背包]

    Team Them Up! Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7608   Accepted: 2041   S ...

  9. UVALive 4849 String Phone(2-sat、01染色)

    题目一眼看去以为是4-sat... 题意:给n(n<=3000)个黑方块的坐标,保证黑方块没有公共边.对于每个黑方块选一个角作为结点,使得所选结点满足输入的一个无向图.其中距离为曼哈顿距离.输出 ...

随机推荐

  1. docker 使用教程1

    1.概念理解 镜像:docker镜像就像一个个模具. 容器:docker容器就是模具翻模出来的东西. 仓库:仓库就是存放模具的地方. 下面通过运行 hello-world 来理解 docker镜像运行 ...

  2. svg基础--基本语法与标签

    svg系列–基础 这里会总结svg的基础知识和一些经典的案例. svg简介 SVG(Scalable Vector Graphics)is an XML-based Language for crea ...

  3. 使用sqoop将mysql数据导入到hive中

    首先准备工具环境:hadoop2.7+mysql5.7+sqoop1.4+hive3.1 准备一张数据库表: 接下来就可以操作了... 一.将MySQL数据导入到hdfs 首先我测试将zhaopin表 ...

  4. HTTP 常用状态码200 301 302 403 500

    200(OK):成功处理了请求. 301 redirect: 301 代表永久性转移(Permanently Moved) //助记 1 永恒,如果你记住了这一条就算这篇博客没白写.302 redir ...

  5. AjaxControlToolKit CalendarExtender(日历扩展控件)的使用方法

    设置CalendarExtender的TargetControlID为需要显示日期的TextBox的ID,textBox控件的readOnly属性设置为 false ,这样就可以点击textbox控件 ...

  6. 修改postman工具的代码生成工具让它锦上添花

    @font-face { font-family: octicons-link; src: url("data:font/woff;charset=utf-8;base64,d09GRgAB ...

  7. Solon rpc 之 SocketD 协议 - 消息加密模式

    Solon rpc 之 SocketD 协议系列 Solon rpc 之 SocketD 协议 - 概述 Solon rpc 之 SocketD 协议 - 消息上报模式 Solon rpc 之 Soc ...

  8. epoll的陷阱实践

    在使用epoll的时候,我们上篇文章epoll的陷阱大体介绍了epoll中会有哪些问题.这篇文章我们就针对必须要了解,也是绕不过去的陷阱进行实验,看看现象是什么,并且如何编写才能达到我们想要的效果. ...

  9. 【剑指 Offer】11.旋转数组的最小数字

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的 ...

  10. Kubernetes学习笔记之安装minikube并运行个简单应用程序

    前言:本笔记仅记录学习记录,可能存在错误!!!使用的环境是Ubuntu Desktop 20.04,也有用Windows 10 操作的,根据的文档是minikube的文档教程,链接:https://m ...