题目描述

输入输出格式

输入格式:

输出格式:

对于每个询问操作,输出一行答案。

输入输出样例

输入样例#1:

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
输出样例#1:

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]染色的更多相关文章

  1. 洛谷 P2486 [SDOI2011]染色 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...

  2. 洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告

    [SDOI2011]染色 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同 ...

  3. 洛谷 P2486 [SDOI2011]染色 LCT

    Code: #include <cstdio> //SDOI2010 染色 #include <algorithm> #include <cstring> #inc ...

  4. 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...

  5. 洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)

    题目链接 题解 比较裸的树链剖分 好像树链剖分的题都很裸 线段树中维护一个区间最左和最右的颜色,和答案 合并判断一下中间一段就可以了 比较考验代码能力 Code #include<bits/st ...

  6. 洛谷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 ...

  7. 洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)

    [题目链接] [思路]: 涉及到树上区间修改操作,所以使用树链剖分,涉及到区间查询,所以使用线段树. update操作时,就正常操作,难点在于query操作的计数. 因为树链剖分的dfs序只能保证一条 ...

  8. 洛谷$P2486\ [SDOI2011]$染色 线段树+树链剖分

    正解:线段树+树链剖分 解题报告: 传送门$QwQ$ 其实是道蛮板子的题,,,但因为我写得很呆然后写了贼久之后发现想法有问题要重构,就很难受,就先写个题解算了$kk$ 考虑先跑个树剖,然后按$dfn$ ...

  9. BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...

随机推荐

  1. 编译安装Apache httpd和php搭建KodExplorer网盘

    编译安装Apache httpd和php搭建KodExplorer网盘 环境说明: 系统版本    CentOS 6.9 x86_64 软件版本    httpd-2.2.31        php- ...

  2. json-server模拟接口获取mock数据

    转载:http://blog.csdn.net/stevennest/article/details/76167343 安装json-server 运行以下命令 cnpm install json-s ...

  3. Java的位运算

    左移位操作 左移位运算的符号为[<<],左移位运算符左面的操作元称作被移位数,右面的操作数称作移位量. 左移位运算是双目运算符,操作元必须是整型类型的数据,其移动过程是:[a <&l ...

  4. JAVA Eclipse如何重新设置工作空间workspace

    窗口-首选项-常规-启动和关闭,勾选启动时提示工作空间,然后移除现有的工作空间,最好也勾选启动时刷新工作空间   重启之后就可以设置工作空间了  

  5. Linux 下Office 软件名称

    Linux 下Office 软件名称

  6. mybatis like写法

    name like concat(concat('%',#{name}),'%') name like concat('%',#{name},'%')

  7. 谈谈IIS与ASP.NET管道

    作为一个Asp.Net平台开发者,非常有必要了解IIS和Asp.Net是如何结合,执行我们的托管代码,以及Asp.Net管道事件的. 本节目录 IIS 5.X IIS 6 IIS 7+ 集成模式 As ...

  8. xcode几个常用的快捷键

    command + ctrl + e   修改变量的名称:选中某个变量,按下该快捷键,可以批量修改对应的变量名称 command + shift + j 定位到文档导航界面,然后通过上下方向键,可以快 ...

  9. nginx实现某个页面http访问,其余全部跳转到https

    全站https实现某个页面可以http访问,其余全部跳转到https,注意下面的location,如果不加root 配置 找不到这个文件的server { listen ; server_name w ...

  10. nginx适配移动端

    考虑到网站的在多种设备下的兼容性,有很多网站会有手机版和电脑版两个版本.访问同一个网站URL,当服务端识别出用户使用电脑访问,就打开电脑版的页面,用户如果使用手机访问,则会得到手机版的页面. ngin ...