题意:
给定一棵 n 个节点的无根树,共有 m 个操作,操作分为两种:

1.将节点 a 到节点 b 的路径上的所有点(包括 a 和 b)都染成颜色 c。
2.询问节点 a 到节点 b 的路径上的颜色段数量。

颜色段的定义是极长的连续相同颜色被认为是一段。例如 112221 由三段组成:11、222、1。

题解:
树剖+线段树维护区间子段和问题。
如果在在单独的线段树上操作的话,难度还不是特别高,这个题因为转移到了树上去,树剖的本质是把线段树的区间给分成了好几段,所以我们在经过树上路径的时候,衔接位置要特别注意。

一个小细节的地方。!!!
由代码可见,这是两种不同的写法;
出锅的原因:未考虑清楚L1由x决定,那么L2应由x匹配,L2则与y;

if(dep[x]<dep[y])
swap(x,y),swap(ansl,ansr);
ans+=query(1,id[y],id[x],id[y],id[x]);
if(Rc==ansl) ans--;
if(Lc==ansr) ans--;
/*
if(dep[x]>dep[y])
swap(x,y),swap(ansl,ansr);
ans+=query(1,id[x],id[y],id[x],id[y]);
if(Lc==ansl) ans--;
if(Rc==ansr) ans--;*/

代码:

//#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
//#define int long long
const int maxn=1e5+10;
#define endl '\n'struct node{int to,next;
}edge[maxn*2];int a[maxn],head[maxn*2],dep[maxn];
int f[maxn],sz[maxn],son[maxn];
int tot;int n,m;
void add(int u,int v){edge[tot].to=v,edge[tot].next=head[u];head[u]=tot++;edge[tot].to=u,edge[tot].next=head[v];head[v]=tot++;
}void dfs1(int x,int fa){f[x]=fa;dep[x]=dep[fa]+1;sz[x]=1;for(int i=head[x];~i;i=edge[i].next){int to=edge[i].to;if(to==fa) continue;dfs1(to,x);sz[x]+=sz[to];if(sz[to]>sz[son[x]]) son[x]=to;}
}int dfn[maxn],top[maxn],w[maxn];
int cnt;
void dfs2(int x,int t){dfn[x]=++cnt;top[x]=t;w[cnt]=a[x];if(!son[x]) return ;dfs2(son[x],t);for(int i=head[x];~i;i=edge[i].next){int to=edge[i].to;if(to==f[x]||to==son[x]) continue;dfs2(to,to);}
}
int lcol[maxn*4],rcol[maxn*4],tree[maxn*4];void push_up(int node){if(rcol[node*2]==lcol[node*2+1]){tree[node]=tree[node*2]+tree[node*2+1]-1;}else tree[node]=tree[node*2]+tree[node*2+1];lcol[node]=lcol[node*2];rcol[node]=rcol[node*2+1];
}
void build(int node,int start,int ends){if(start==ends){tree[node]=1;lcol[node]=rcol[node]=w[start];return ;}int mid=(start+ends)/2;build(node*2,start,mid);build(node*2+1,mid+1,ends);push_up(node);
}
int lazy[maxn*4];
void push_down(int node){if(lazy[node]!=0){lazy[node*2]=lazy[node*2+1]=lazy[node];lcol[node*2]=rcol[node*2]=lcol[node*2+1]=rcol[node*2+1]=lazy[node];tree[node*2]=tree[node*2+1]=1;lazy[node]=0;}
}void update(int node,int start,int ends,int l,int r,int val){if(l<=start&&ends<=r){tree[node]=1;lcol[node]=rcol[node]=lazy[node]=val;return ;}int mid=(start+ends)/2;push_down(node);if(l<=mid) update(node*2,start,mid,l,r,val);if(mid<r) update(node*2+1,mid+1,ends,l,r,val);push_up(node);
}int querycnt(int node,int start,int ends,int l,int r,int &ansl,int &ansr){if(l<=start&&ends<=r){if(l==start) ansl=lcol[node];if(r==ends) ansr=rcol[node];return tree[node];}int mid=(start+ends)/2;push_down(node);int res=0;if(l<=mid) res+=querycnt(node*2,start,mid,l,r,ansl,ansr);if(mid<r) res+=querycnt(node*2+1,mid+1,ends,l,r,ansl,ansr);if(rcol[node*2]==lcol[node*2+1]&&l<=mid&&mid<r) return res-1;else  return res;
}//int querycol(int node,int start,int ends,int pos){//    if(start==ends) return lcol[node];
//    int mid=(start+ends)/2;
//    push_down(node);
//    if(pos<=start) return querycol(node*2,start,mid,pos);
//    else return querycol(node*2+1,mid+1,ends,pos);
//}void upchain(int x,int y,int val){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);update(1,1,n,dfn[top[x]],dfn[x],val);x=f[top[x]];}if(dep[x]>dep[y]) swap(x,y);update(1,1,n,dfn[x],dfn[y],val);
}
int querychain(int x,int y){int res=0;int L1=-1,L2=-1,Lc,Rc;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]){swap(x,y);swap(L1,L2);}res+=querycnt(1,1,n,dfn[top[x]],dfn[x],Lc,Rc);
//        cout<<" l "<<dfn[top[x]]<<" r "<<dfn[x]<<endl;
//        cout<<"debug "<<res<<endl;if(L1==Rc) res--;L1=Lc;x=f[top[x]];}if(dep[x]<dep[y]){swap(x,y);swap(L1,L2);}res+=querycnt(1 ,1,n,dfn[y],dfn[x],Lc,Rc);if(Rc==L1) res--;if(Lc==L2) res--;return res;
}
signed main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);memset(head,-1,sizeof head);cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<n;i++){int x,y;cin>>x>>y;add(x,y);}dfs1(1,1);dfs2(1,1);build(1,1,n);//    for(int i=1;i<=n;i++){//        cout<<"dfn  "<<i<<" "<<top[i]<<endl;
//    }for(int i=1;i<=m;i++){char opt;cin>>opt;if(opt=='C'){int x,y,z;cin>>x>>y>>z;upchain(x,y,z);}else{int x,y;cin>>x>>y;cout<<querychain(x,y)<<endl;}}}

[SDOI2011]染色 (线段树维护子段问题+树剖)相关推荐

  1. YBTOJ:采矿战略(线段树维护dp、树链剖分)

    文章目录 题目描述 解析 代码 题目描述 所谓线段树维护dp,就是在线段树上维护dp (逃) 解析 把树剖一下后就变成了区间问题 考虑建一棵线段树,每一个结点都是一个背包 这样就能区间查询,也能带修了 ...

  2. [Bzoj2243][SDOI2011]染色(线段树树剖)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2243 线段树+树链剖分,在线段树需要每次用lt和rt两个数组记录当前区间的左右边界的颜色 ...

  3. Can you answer these queries V SPOJ - GSS5 (分类讨论+线段树维护区间最大子段和)

    recursion有一个整数序列a[n].现在recursion有m次询问,每次她想知道Max { A[i]+A[i+1]+...+A[j] ; x1 <= i <= y1 , x2 &l ...

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

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

  5. 线段树维护(最大区间和,最大子段和,最长连续上升子序列)

    本文主要介绍用线段树来维护(最大区间和,最大子段和,最长连续上升子序列)的问题. HDU 1540 Tunnel Warfare(最长连续区间+单点修改) 洛谷 P2894 [USACO08FEB]酒 ...

  6. Can you answer these queries III (线段树维护最大子段和)

    题意: 求一个区间的最大连续和. 0:表示把A[x]改成y 1:表示求[x,y]这个区间的最大连续和. 题解: 线段树维护四个变量. 倒着讲,先来看如何维护这四个变量. summax代表这个区间连续最 ...

  7. 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 ...

  8. 线段树维护区间最大值+第 45 届(ICPC)亚洲区域赛(昆明)L题Simone and Graph Coloring

    题意: 给你n个数的序列,当满足i<ji<ji<j andandand ai>aja_i>a_jai​>aj​时,这两个点之间有一条边,现在对点染色,要求每个点相邻 ...

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

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

最新文章

  1. springboot mysql行锁_SpringBoot基于数据库实现简单的分布式锁
  2. PHP和ajax详解
  3. css+图标偏移,css background-position 偏移的问题
  4. Hibernate之对象关系映射文件
  5. C#-WinForm跨线程修改UI界面
  6. 计算机网络(八)-数据链路层-帧封装
  7. bind() c语言,c/c++ 标准库 bind 函数详解
  8. 机器人多用途综合官网展示PHP单页源码
  9. SLAM_怎么评价slam建图效果
  10. vue-router的两种模式
  11. cesium 实现指南针及比例尺效果
  12. 美国拉斯维加斯游戏CRAPS(花旗骰)掷骰子的游戏的C语言版本
  13. Pandas的时间序列Period,period_range---详解(29)
  14. c语言如何编程硬件,很多硬件开发都用C语言编程.PPT
  15. Ubuntu Desktop LTS - 安装 64 位谷歌 Chrome 浏览器
  16. 深度学习(十)人脸识别与神经风格迁移
  17. python计算1的平方减2的平方加3的平方减4的平方怎么算_计算1的平方减2的平方加3的平方减4的平方 – 手机爱问...
  18. (免费分享)基于ssm的BBS社区论坛系统带论文
  19. 网页中的三种地址详解
  20. 【Excel 教程系列第 7 篇】多张图片如何居中单元格?

热门文章

  1. TCP网络应用程序的注意点
  2. Java技术体系平台
  3. 基于OpenCV的透视图转化为不同平面
  4. 第二篇:n-gram 语言模型
  5. 链表问题10——两个单链表生成相加链表(方法二)
  6. Three levels at which any machine carrying out an Information-Processing task must be understood
  7. 结对编程-马尔科夫链作业成绩
  8. [Android Traffic] 调整定时更新的频率(C2DM与退避算法)
  9. bootstrap datepicker Uncaught TypeError: Cannot call method 'split' of undefined问题
  10. Windows Phone 7 开“.NET研究”发之:工具栏