2243: [SDOI2011]染色

>原题链接<

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

Sample Output

3
1
2

HINT

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

思路:

  显然,这道题我们可以通过在整颗树上架一颗线段树、然后进行区间修改区间查询的操作。而询问a到b的路径,显然是a到lca(a,b)的路径和 b到lca(a,b)的路径的并。所以我们可以使用先树链剖分再在剖分序列上架线段树的方式维护这样的连续区间。通过在dfs2的时候给每个点压入队列确定顺序,再在LCA的时候对每段进行查询,即可得到每次的答案;

至于线段树的操作,本题显然是一道区间合并的线段树,我们可以维护如下三种信息:区间左端点颜色,区间右端点颜色、区间颜色段数目。在pushup时,若左子树的右端点和右子树的左端点颜色相同,则是同一段颜色,sum[p] = sum[ls]+sum[rs] - 1,否则是两段颜色,不需要-1 。值得注意的是,本题的颜色范围是[0,1e9],所以在打lazy_tag时,要注意laz的初始值,不能是0,。但是我选择把所有输入的颜色++,相当于区间平移,不会对答案产生影响。

  另外,本题函数非常多,可以用结构体封装以增加代码清晰度,我选择了用class封装,但是可能会稍微慢一点。

代码如下

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cctype>
#define ls p<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define im int mid = (l + r) >> 1
using namespace std;
const int N = 1100000;
int son[N],siz[N],fa[N],top[N],dep[N];
int idx[N],idy[N],cnt2;
int to[N<<1],next[N<<1],pval[N],head[N],cnt1;
int n,m;
class ReadIn {private:inline char nc() {static char buf[100000], *p1, *p2;return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}public:inline int read() {int x=0;char ch=nc();while(!isdigit(ch))ch=nc();while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=nc();}return x;}inline char getc() {char ch=nc();while(isspace(ch))ch=nc();return ch;}
}Rd;
class SegmentTree {private:int lft[N<<2],rft[N<<2],sum[N<<2],laz[N<<2];void pushdown(int p) {if(!laz[p]) return ;else {sum[ls]=sum[rs]=1;lft[ls]=laz[ls]=rft[ls]=lft[rs]=laz[rs]=rft[rs]=laz[p];}laz[p]=0;return;}void pushup(int p) {sum[p]=sum[ls]+sum[rs];if(rft[ls]==lft[rs])sum[p]--;lft[p]=lft[ls];rft[p]=rft[rs];}public:void build(int l,int r,int p) {if(l==r) {lft[p]=rft[p]=pval[idy[l]];sum[p]=1;return ;}im;build(lson);build(rson);pushup(p);return ;}int query(int l,int r,int p,int x,int y) {pushdown(p);if(x<=l&&y>=r) {return sum[p];}im;if(y<=mid)return query(lson,x,y);else if(x>mid)return query(rson,x,y);else {int re = query(lson,x,y)+query(rson,x,y);;if(rft[ls]==lft[rs])re--;return re;}}void change(int l,int r,int p,int x,int y,int c) {if(x<=l&&y>=r) {laz[p]=c;sum[p]=1;lft[p]=rft[p]=laz[p];return;}im;pushdown(p);if(x<=mid)change(lson,x,y,c);if(y>mid)change(rson,x,y,c);pushup(p);}int find(int l,int r,int p,int x) {pushdown(p);if(l==r) return lft[p];im;if(x<=mid) return find(lson,x);else return find(rson,x);}
}Tr;
class TreeChainDissection {public:void dfs1(int p) {dep[p]=dep[fa[p]]+1;siz[p]=1;for (int i = head[p];i; i = next[i] ) {if(to[i] != fa[p]) {fa[to[i]]=p;dfs1(to[i]);siz[p]+=siz[to[i]];if(siz[to[i]]>siz[son[p]])son[p]=to[i];}}}void dfs2(int p,int t) {idx[p]=++cnt2;idy[cnt2]=p;top[p]=t;if(son[p]) dfs2(son[p],t);for(int i=head[p];i;i=next[i])if(to[i]!=fa[p]&&to[i]!=son[p])dfs2(to[i],to[i]);}int lcaq(int a,int b) {int ans=0;while(top[a]!=top[b]) {if(dep[top[a]]>dep[top[b]])swap(a,b);int upc = Tr.find(1,n,1,idx[fa[top[b]]]);int doc = Tr.find(1,n,1,idx[top[b]]);ans+= Tr.query(1,n,1,idx[top[b]],idx[b]);if(upc==doc) ans--;//printf("%d\n",ans);b=fa[top[b]];}if(dep[a]<dep[b])swap(a,b);ans+=Tr.query(1,n,1,idx[b],idx[a]);if(!ans)ans=1;return ans;}void lcac(int x,int y,int z) {while(top[x]!=top[y]){if(dep[top[x]]>dep[top[y]])swap(x,y);Tr.change(1,n,1,idx[top[y]],idx[y],z);y=fa[top[y]];}if(dep[x]<dep[y])swap(x,y);Tr.change(1,n,1,idx[y],idx[x],z);}}Tcd;
class Pre {private:inline void add_edge(int a,int b) {to[++cnt1] = b;next[cnt1] = head[a];head[a] = cnt1;to[++cnt1] = a;next[cnt1] = head[b];head[b] = cnt1;}public:void init() {n=Rd.read(),m=Rd.read();int i,x,y;for(i=1 ;i <=n; i++) pval[i] = Rd.read() + 1;for(i=1 ;i < n; i++) {x=Rd.read(),y=Rd.read();add_edge(x,y);}}
}Pr;
void solve() {Tcd.dfs1(1);Tcd.dfs2(1,1);Tr.build(1,n,1);int i,x,y,z;char opt;for(i=1;i<=m;i++) {opt=Rd.getc();if(opt=='Q') {x=Rd.read();y=Rd.read();int ans=Tcd.lcaq(x,y);printf("%d\n",ans);}else {x=Rd.read(), y=Rd.read(), z=Rd.read();Tcd.lcac(x,y,z+1);}}
}
int main() {Pr.init();solve();
}

欢迎来原博客看看 >原文链接<

转载于:https://www.cnblogs.com/Tobichi/p/9081455.html

BZOJ 2243: [SDOI2011]染色相关推荐

  1. 【BZOJ 2243】染色

    传送门:洛谷   BZOJ 还不会LCT的小伙伴可以看一下这篇博客:LCT总结 我初学动态树时就是看着那篇博客学的,写的很好! 那好 言归正传. 显然树上 x 到 y 的路径的问题都可以用LCT Ac ...

  2. BZOJ 2243 染色(树链剖分好题)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 7971  Solved: 2990 [Submit][Stat ...

  3. P2486 [SDOI2011]染色

    P2486 [SDOI2011]染色 题意: 题解: 与一般的树链剖分相比,不同点在于查询的不是路径上颜色的数量而是颜色段的数量 对于两个颜色段,112和221,两个颜色段数量都是2 如果合在一起颜色 ...

  4. [Luogu 2486] SDOI2011 染色

    [Luogu 2486] SDOI2011 染色 树剖水题,线段树维护. 详细题解不写了. 我只想说我写的线段树又变漂亮了qwq #include <algorithm> #include ...

  5. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

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

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

  7. [BZOJ 2243] 染色

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2243 分析 树链剖分练习题 比较难的地方在于两端相邻区间交界处的颜色有可能相同. 那么此时查询 ...

  8. [SDOI2011]染色

    题目:染色 传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 分析: (1)很裸的树链剖分,然而我忘了树剖怎么打(其实是代码太长不想打, ...

  9. BZOJ 2303 方格染色(带权并查集)

    要使得每个2*2的矩形有奇数个红色,如果我们把红色记为1,蓝色记为0,那么我们得到了这2*2的矩形里的数字异或和为1. 对于每个方格则有a(i,j)^a(i-1,j)^a(i,j-1)^a(i-1,j ...

最新文章

  1. JS获取当月每天的日期,JS获取本周每天的日期
  2. python得到一个excel的全部sheet标签值
  3. 2016蓝桥杯省赛---java---C---8(冰雹数)
  4. 系统架构设计师 - 信息安全技术
  5. postman发送HTTP请求自动生成MD5签名
  6. 前景菜谱制作的seo技巧
  7. 句句真研—每日长难句打卡Day8
  8. Java 会是未来第一编程语言吗?
  9. wap ios android,iOS/Android/WAP 全兼容专题页面制作方法(一)
  10. 83页XX市高速智慧公路总体建设方案
  11. 计算机为何引入16进制,计算机内存地址为什么要用16进制数来表示
  12. aspose给word添加水印
  13. PostgreSQL查询 动态输入参数
  14. 【Spring学习笔记 九】Spring声明式事务管理实现机制
  15. 计算机考研报录比10比1,考研报录比10:1高么
  16. 自己动手丰衣足食之征服jQuery插件编写
  17. wdcp 如何创建用IP就可以访问的默认站点/修改默认站点
  18. MacBookPro M1 多屏扩展解决方案
  19. C/C++项目开发:教你用C++开发电脑桌面提醒程序,好厉害的黑科技!
  20. 2011杭电研究生复试-------…

热门文章

  1. 社招转行进腾讯了(自学经验 + 面试心得)
  2. 搜狗浏览器安装自定义JS脚本的方法~
  3. formidable词根词缀_实用文档之英语单词(词根词缀)
  4. 使用vscode编写小程序并同步
  5. 使用pycharm去掉表格中的重复数据
  6. 一位励志的盲人程序员加我微信,求助找工作
  7. gred-cam 的tensorflow实现 热力图
  8. 第十九周学习周报(20180709-20180715)
  9. Pr速成3小时学会视频剪辑[副业学习会]
  10. 中国大学MOOC-翁恺-C语言程序设计习题集(学习笔记)