目录

  • 题面

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

题面

题目链接

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

说明

【数据规模】

【时空限制】

1000ms,128M

思路

看题,操作从a到b的路径上所有点,可以想到树剖。

然而这一题要求的结果有点迷,如果是线段树,第一感觉是要用线段树合并。结构体里面保存 最左端的颜色nowl最右端的颜色nowr ,在两个线段树合并时, 该区间内颜色段数量sum 需要作一下判断:如果左儿子的最右端和右儿子的最左端颜色相同,那么sum应该是左儿子和右儿子的sum之和减1;否则是左儿子和右儿子的sum之和。

基本思路确定了,再看看实际。。。

PushDown与Update

void Update(int p)
{s(p)=s(p<<1)+s(p<<1|1);if(nr(p<<1)==nl(p<<1|1)) s(p)--; ///如上所说的判断nl(p)=nl(p<<1);nr(p)=nr(p<<1|1);
}
void PushDown(int p)
{if(t(p)){s(p<<1)=s(p<<1|1)=1; ///此时两个儿子的sum都是1nl(p<<1)=nr(p<<1)=nl(p<<1|1)=nr(p<<1|1)=t(p<<1)=t(p<<1|1)=t(p);  ///左、右儿子最左、最右结点,还有懒标记全部变成了现在染上的颜色t(p)=0;}
}

Q

本来以为查询操作也是线段树合并,然后写了一半发现不对劲,因为查询的路径上新给定的标号nid是不连续的!不过,nid不连续,我们可以直接判断。

int Ask2(int u,int v)
{int ans=0;while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]]) swap(u,v);SegmentTree tmp=Ask1(1,nid[top[u]],nid[u]);ans+=tmp.sum; ///统计答案的时候把单独的这条链的颜色段数量加上if(tmp.nl==Ask1(1,nid[fa[top[u]]],nid[fa[top[u]]]).nr) ans--; ///考虑到,如果这条链可以和下一条链合并,那必然是他和他的父亲合并,所以这个时候只要判断他和他父亲颜色是否相同,来判断是否要减1u=fa[top[u]];}if(dep[u]>dep[v]) swap(u,v);ans+=Ask1(1,nid[u],nid[v]).sum;return ans;
}

AC代码

#include<bits/stdc++.h>
const int maxn=100010;
using namespace std;int n,m,wt[maxn];
int tot,to[maxn<<1],nxt[maxn<<1],head[maxn];
int son[maxn],fa[maxn],len[maxn],dep[maxn];
int cnt,nid[maxn],nw[maxn],top[maxn];
struct SegmentTree
{int l,r,sum,nl,nr,tag;#define l(a) tree[a].l#define r(a) tree[a].r#define m(a) ((l(a)+r(a))>>1)#define len(a) (r(a)-l(a)+1)#define s(a) tree[a].sum#define nl(a) tree[a].nl#define nr(a) tree[a].nr#define t(a) tree[a].tag
}tree[maxn<<2];void dfs1(int u,int f,int d)
{fa[u]=f;dep[u]=d;len[u]=1;for(int i=head[u];i;i=nxt[i]){int v=to[i];if(v==f) continue;dfs1(v,u,d+1);len[u]+=len[v];if(len[v]>len[son[u]]) son[u]=v;}
}void dfs2(int p,int t)
{nid[p]=++cnt;nw[cnt]=wt[p];top[p]=t;if(!son[p]) return;dfs2(son[p],t);for(int i=head[p];i;i=nxt[i]){int v=to[i];if(v==fa[p] || v==son[p]) continue;dfs2(v,v);}
}void Update(int p)
{s(p)=s(p<<1)+s(p<<1|1);if(nr(p<<1)==nl(p<<1|1)) s(p)--;nl(p)=nl(p<<1);nr(p)=nr(p<<1|1);
}void BuildTree(int p,int l,int r)
{l(p)=l;r(p)=r;if(l==r){s(p)=1;nl(p)=nr(p)=nw[l];return;}BuildTree(p<<1,l,m(p));BuildTree(p<<1|1,m(p)+1,r);Update(p);
}void PushDown(int p)
{if(t(p)){s(p<<1)=s(p<<1|1)=1;nl(p<<1)=nr(p<<1)=nl(p<<1|1)=nr(p<<1|1)=t(p<<1)=t(p<<1|1)=t(p);t(p)=0;}
}void Change1(int p,int l,int r,int k)
{if(l<=l(p) && r>=r(p)){s(p)=1;nl(p)=nr(p)=t(p)=k;return;}PushDown(p);if(l<=m(p)) Change1(p<<1,l,r,k);if(r>m(p)) Change1(p<<1|1,l,r,k);Update(p);
}void Change2(int u,int v,int k)
{while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]]) swap(u,v);Change1(1,nid[top[u]],nid[u],k);u=fa[top[u]];}if(dep[u]>dep[v]) swap(u,v);Change1(1,nid[u],nid[v],k);
}SegmentTree Ask1(int p,int l,int r)
{if(l<=l(p) && r>=r(p)) return tree[p];PushDown(p);if(r<=m(p)) return Ask1(p<<1,l,r);else if(l>m(p)) return Ask1(p<<1|1,l,r);else{SegmentTree a=Ask1(p<<1,l,r),b=Ask1(p<<1|1,l,r),tmp;tmp.nl=a.nl;tmp.nr=b.nr;tmp.sum=a.sum+b.sum;if(a.nr==b.nl) tmp.sum--;return tmp;}
}int Ask2(int u,int v)
{int ans=0;while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]]) swap(u,v);SegmentTree tmp=Ask1(1,nid[top[u]],nid[u]);ans+=tmp.sum;if(tmp.nl==Ask1(1,nid[fa[top[u]]],nid[fa[top[u]]]).nr) ans--;u=fa[top[u]];}if(dep[u]>dep[v]) swap(u,v);ans+=Ask1(1,nid[u],nid[v]).sum;return ans;
}int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d",&wt[i]);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);to[++tot]=v;nxt[tot]=head[u];head[u]=tot;to[++tot]=u;nxt[tot]=head[v];head[v]=tot;}dfs1(1,1,1);dfs2(1,1);BuildTree(1,1,n);for(int i=1;i<=m;i++){char ch;cin>>ch;int u,v,k;scanf("%d%d",&u,&v);if(ch=='C'){scanf("%d",&k);Change2(u,v,k);}else printf("%d\n",Ask2(u,v));}return 0;
}

总结与拓展

感觉有点没讲清楚。这道题写完应该是对树剖有了进一步的巩固。

转载于:https://www.cnblogs.com/Mercury04/p/9713763.html

洛谷 P2486 [SDOI2011]染色 树链剖分相关推荐

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

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

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

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

  3. 专题·树链剖分【including 洛谷·【模板】树链剖分

    初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...

  4. 洛谷 P2486 [SDOI2011]染色 LCT

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

  5. 洛谷P4114 Qtree1(树链剖分+线段树)

    传送门 LCT秒天秒地用什么树剖 这题可以算是树剖的比较裸的题目了 把每一条边的权值下放到他两边的点中深度较深的那个 然后直接用树剖+线段树带进去乱搞就可以了 1 //minamoto 2 #incl ...

  6. HYSBZ - 2243染色——树链剖分+线段树建树技巧

    [题目描述] HYSBZ - 2243染色 [题目分析] 我一直没有看清楚题,以为求的是路径上出现颜色的种类,然后就写了一个区间染色的线段树进行维护,过样例的时候才发现题读错了,人家要求的是路径上出现 ...

  7. 洛谷2486 【SDOI2011】染色(线段树+树链剖分)

    传送门 [题目分析] 果然重构才是真理吗..... 因为涉及路径操作,所以考虑树链剖分,线段树维护题意中的: 1.区间颜色段数. 2.区间左右颜色. 3.区间覆盖标记. 因为线段树的问题主要就是考虑p ...

  8. 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 2 1 1 Q ...

  9. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释...

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

最新文章

  1. Dalvik VM和Java VM的区别:
  2. 【机器学习基础】8个知识点,图解K-Means算法
  3. ps字体识别_PS字体包免费送:艺术+时尚+炫酷+复古等5000多款字体,由你来选择
  4. 中国大学MOOC 计算机组成原理第5章 测试(上)
  5. 牛客网_PAT乙级_1017打印沙漏(20)
  6. OSI模型和TCP/IP协议族
  7. 使用ABP打造SAAS系统(2)——前端框架选择
  8. 分布式系统:CAP 理论的前世今生
  9. python解析html的库_python自带的用于解析HTML的库HtmlParser
  10. Git 的origin和master分析 push/diff/head
  11. ios开发 将json格式数据上传服务器
  12. 饥荒联机版服务器重置,饥荒联机版服务器重置世界 | 手游网游页游攻略大全
  13. C++_SHFileOperation文件夹操作
  14. 通过Log4j生成CSV格式日志时自动插入表头处理方法
  15. UITableView在iOS15中显示混乱的问题
  16. 一加6android p上手,一加6秒速跟进安卓P 教你尝鲜速成开发者
  17. matlab计算两向量的乘积,matlab中两个函数相乘
  18. Win7旗舰版电脑插耳机没声音怎么解决
  19. 2022年网搭国赛PXE服务
  20. 分享一篇企鹅的暑期实习生技术面经验

热门文章

  1. 压缩感知及应用 源代码_信言动态|学院成功举办2019年机器学习与压缩感知理论及其应用研讨会...
  2. python教材答案字典与集合_Python——集合与字典练习
  3. java生成8位邀请码,邀请码生成器Java代码
  4. java许愿墙_wishingWall 一个好看的许愿墙板块,功能强大,页面美观 Java Develop 238万源代码下载- www.pudn.com...
  5. java zip 文件夹_Java Zip文件文件夹示例
  6. t–sql pl–sql_SQL存储过程–终极指南
  7. easymock参数_EasyMock捕获参数
  8. Python输入,输出,Python导入
  9. python hash函数_Python hash()函数
  10. 看看ConcurrentLinkedQueue源码 in Java 9