洛谷 P2486 [SDOI2011]染色
题目描述

输入输出格式
输入格式:

输出格式:
对于每个询问操作,输出一行答案。
输入输出样例
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
说明


题解:
树剖,用线段树维护:
数组tot[N]表示此时的颜色段数。
数组zzz[N]表示此时最左边的节点的颜色。
数组yyy[N]表示此时最右边的节点的颜色。
则: 首先我们要明确,线段树的叶子节点一定只有一种颜色,也就是一条颜色段。
tot[父亲]=tot[左儿子]+tot[右儿子];
if (zzz[右儿子]==yyy[左儿子]) {tot[父亲]--;}
即如果右儿子的最左边颜色和左儿子的最右边颜色相同,那么肯定有中间部分属于同一颜色段。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#define k (z+y>>1)
#define ll (r<<1)
#define rr (r<<1|1)
using namespace std;
const int N=1e5+;int a[N];
int ys[N],s[N*][],o[N],cnt,dfn,n;
int zzz[N*],yyy[N*],laz[N*],tot[N*];
int d[N],siz[N],son[N],top[N],f[N],id[N];
void jia(int a,int b)
{
s[++cnt][]=o[a];
s[cnt][]=b;o[a]=cnt;
return;
}
void shang(int r)
{
tot[r]=tot[ll]+tot[rr];
zzz[r]=zzz[ll];yyy[r]=yyy[rr];
if (zzz[rr]==yyy[ll]) tot[r]--;
return;
}
void xiangxia(int r,int z,int y)
{
tot[ll]=tot[rr]=;
zzz[ll]=zzz[rr]=yyy[ll]=yyy[rr]=laz[ll]=laz[rr]=laz[r];
laz[r]=;return;
}
void jianshu(int r,int z,int y)
{
if (z==y) {
tot[r]=;zzz[r]=yyy[r]=ys[a[z]];
return;
}
jianshu(ll,z,k);jianshu(rr,k+,y);
shang(r);return;
}
void gai(int r,int z,int y,int zz,int yy,int v)
{
if (z==zz&&y==yy) {
tot[r]=;laz[r]=zzz[r]=yyy[r]=v;
return;
}
if (laz[r]) xiangxia(r,z,y);
if (zz>k) gai(rr,k+,y,zz,yy,v);
else if (yy<=k) gai(ll,z,k,zz,yy,v);
else {gai(ll,z,k,zz,k,v);gai(rr,k+,y,k+,yy,v);}
shang(r);return;
}
int chaxun(int r,int z,int y,int zz,int yy)
{
if (z==zz&&y==yy) return tot[r];
if (laz[r]) xiangxia(r,z,y);
if (zz>k) chaxun(rr,k+,y,zz,yy);
else if (yy<=k) chaxun(ll,z,k,zz,yy);
else {
int ans=chaxun(ll,z,k,zz,k)+chaxun(rr,k+,y,k+,yy);
if (zzz[rr]==yyy[ll]) ans--;
return ans;
}
}
void dfs1(int x,int fa,int dep)
{
f[x]=fa;d[x]=dep;siz[x]=;
for (int i=o[x];i;i=s[i][]) {
if (s[i][]!=fa) {
dfs1(s[i][],x,dep+);
siz[x]+=siz[s[i][]];
if (siz[s[i][]]>siz[son[x]]) son[x]=s[i][];
}
}
return;
}
void dfs2(int x,int tp)
{
top[x]=tp;id[x]=++dfn;a[dfn]=x;
if (son[x]) dfs2(son[x],tp);
for (int i=o[x];i;i=s[i][])
if (s[i][]!=f[x]&&son[x]!=s[i][])
dfs2(s[i][],s[i][]);
return;
}
void ranse(int x,int y,int v)
{
while (top[x]!=top[y]) {
if (d[top[x]]>d[top[y]]) swap(x,y);
gai(,,n,id[top[y]],id[y],v);
y=f[top[y]];
}
if (d[x]>d[y]) swap(x,y);
gai(,,n,id[x],id[y],v);
return;
}
int newww(int r,int z,int y,int p)
{
if (z==y) return zzz[r];
if (laz[r]) xiangxia(r,z,y);
if (p>k) return newww(rr,k+,y,p);
else return newww(ll,z,k,p);
}
int xunwen(int x,int y)
{
int ans=,nc,fc;
while (top[x]!=top[y]) {
if (d[top[x]]>d[top[y]]) swap(x,y);
ans+=chaxun(,,n,id[top[y]],id[y]);
nc=newww(,,n,id[top[y]]);
fc=newww(,,n,id[f[top[y]]]);
y=f[top[y]];if (nc==fc) ans--;
}
if (d[x]>d[y]) swap(x,y);
ans+=chaxun(,,n,id[x],id[y]);
return ans?ans:;
}
int main()
{
int m,a,b,c;
cin>>n>>m;char caozuo[];
for (int i=;i<=n;i++) scanf("%d",&ys[i]);
for (int i=;i<n;i++) {
scanf("%d%d",&a,&b);jia(a,b);jia(b,a);
}
dfs1(,,);dfs2(,);jianshu(,,n);
while (m--) {
scanf("%s",caozuo);
scanf("%d%d",&a,&b);
switch (caozuo[]) {
case 'C':scanf("%d",&c);
ranse(a,b,c);break;
default: printf("%d\n",xunwen(a,b));break;
}
}
//zhu wo zao dian AC!!!
return ;
}
ok!!!
洛谷 P2486 [SDOI2011]染色的更多相关文章
- 洛谷 P2486 [SDOI2011]染色 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...
- 洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告
[SDOI2011]染色 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同 ...
- 洛谷 P2486 [SDOI2011]染色 LCT
Code: #include <cstdio> //SDOI2010 染色 #include <algorithm> #include <cstring> #inc ...
- 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...
- 洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)
题目链接 题解 比较裸的树链剖分 好像树链剖分的题都很裸 线段树中维护一个区间最左和最右的颜色,和答案 合并判断一下中间一段就可以了 比较考验代码能力 Code #include<bits/st ...
- 洛谷P2486 [SDOI2011]染色
题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例#1: 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C ...
- 洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)
[题目链接] [思路]: 涉及到树上区间修改操作,所以使用树链剖分,涉及到区间查询,所以使用线段树. update操作时,就正常操作,难点在于query操作的计数. 因为树链剖分的dfs序只能保证一条 ...
- 洛谷$P2486\ [SDOI2011]$染色 线段树+树链剖分
正解:线段树+树链剖分 解题报告: 传送门$QwQ$ 其实是道蛮板子的题,,,但因为我写得很呆然后写了贼久之后发现想法有问题要重构,就很难受,就先写个题解算了$kk$ 考虑先跑个树剖,然后按$dfn$ ...
- BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...
随机推荐
- EffectiveJava(3)使用是由构造器或枚举类型强化singleton
使用是由构造器或枚举类型强化singleton 普通singleton:借助AccessibleObject.setAssess方法,通过反射机制调用私有构造器.抵御这种攻击可以修改构造器,让其再被要 ...
- Android Crash 定位
本文介绍了如何在 Android 手机发生 Crash 时进行 Log 分析的方法, 它可以帮助测试人员快速定位 Android 手机 Crash 发生的原因,同时给研发人员提供有效修改 Bug 的 ...
- odoo12新特性: 会计改进
改进分析会计 分析会计层级结构 分析分配 分析分录增加了表格视图 ============== SPECIFICATIONS ============== a. Hierarchy - Cr ...
- C/C++中字符串与数字之间的转换
主要有两种方式:C 中能够使用 sprintf 将数字转为字符数组,sscanf 将字符数组转为数字:而在 C++ 中不仅能够使用 C 中的方法,还能够使用 stringstream 实现字符串与数字 ...
- ps选框工具全解
我们每次选择工具的时候,ps上面都会变成特定的选项,比如说下面这些: 比如说选区工具的话就分为新选区.添加选区.交叉选区之类的,这些都是需要在实战中练习的. 不单单是选区有这个工具,其他的也有这个功能 ...
- 使用rsa进行http传输加密
目录 1. RSA算法 2. HTTPS 2.1 HTTPS优点 2.2 HTTPS缺点 3. RSA传输加密实现 3.1 所需插件 3.1.1 JS插件 3.1.2 所需JAR 3.1.3 代码 4 ...
- ISE封装IP
1.综合成ngc文件,然后再黑盒调用,再写一个端口文件(写个空壳文件,就是定义输入输出,在工程里面调用这个文件就行,把ngc放到工程目录下).
- hdu 5371 Hotaru's problem【manacher】
题目链接: http://acm.hdu.edu.cn/showproblem.php? pid=5371 题意: 给出一个长度为n的串,要求找出一条最长连续子串.这个子串要满足:1:能够平均分成三段 ...
- BMP图片的C++水印算法
http://wenku.baidu.com/link?url=aVenUhViH9f6At4Lj_As7Rzp_eJWXTcmbUTH0qazd1Y1ZYiU3i1j0pM3G0r_PViIecsv ...
- oracle中提高order by的性能
1.如果order by columnA,那么在where查询条件中添加条件columnA=value,则oracle内部会过滤order by排序,直接用索引(可以通过execution plan查 ...