#树链剖分,线段树#洛谷 2486 [SDOI2011]染色
分析
就是把维护颜色段和树结合起来,
注意拼接的时候要减去中间相同的部分
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=100011; struct node{int y,next;}e[N<<1];
int dep[N],as[N],fat[N],top[N],dfn[N],tot,son[N],n,Lc,Rc,lL,rR,m;
int col[N],nfd[N],big[N],w[N<<2],lazy[N<<2],lc[N<<2],rc[N<<2],k=1;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void add(int x,int y){
e[++k]=(node){y,as[x]},as[x]=k,
e[++k]=(node){x,as[y]},as[y]=k;
}
inline void pup(int k){
lc[k]=lc[k<<1],rc[k]=rc[k<<1|1];
w[k]=w[k<<1]+w[k<<1|1]-(rc[k<<1]==lc[k<<1|1]);
}
inline void pdown(int k){
lc[k<<1]=lc[k<<1|1]=lc[k],lazy[k<<1]=lazy[k<<1|1]=1,
rc[k<<1]=rc[k<<1|1]=rc[k],w[k<<1]=w[k<<1|1]=1,lazy[k]=0;
}
inline void build(int k,int l,int r){
if (l==r){
lc[k]=rc[k]=col[nfd[l]],w[k]=1;
return;
}
rr int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pup(k);
}
inline void update(int k,int l,int r,int x,int y,int z){
if (l==x&&r==y){
lc[k]=rc[k]=z,w[k]=lazy[k]=1;
return;
}
if (lazy[k]) pdown(k);
rr int mid=(l+r)>>1;
if (y<=mid) update(k<<1,l,mid,x,y,z);
else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
else update(k<<1,l,mid,x,mid,z),
update(k<<1|1,mid+1,r,mid+1,y,z);
pup(k);
}
inline signed query(int k,int l,int r,int x,int y){
if (l==x&&r==y){
if (l==lL) Lc=lc[k];
if (r==rR) Rc=rc[k];
return w[k];
}
if (lazy[k]) pdown(k);
rr int mid=(l+r)>>1;
if (y<=mid) return query(k<<1,l,mid,x,y);
else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
else {
rr int ansL=query(k<<1,l,mid,x,mid),
ansR=query(k<<1|1,mid+1,r,mid+1,y);
return ansL+ansR-(rc[k<<1]==lc[k<<1|1]);
}
}
inline void dfs1(int x,int fa){
dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
for (rr int i=as[x],mson=-1;i;i=e[i].next)
if (e[i].y!=fa){
dfs1(e[i].y,x);
son[x]+=son[e[i].y];
if (son[e[i].y]>mson) big[x]=e[i].y,mson=son[e[i].y];
}
}
inline void dfs2(int x,int linp){
dfn[x]=++tot,nfd[tot]=x,top[x]=linp;
if (!big[x]) return; dfs2(big[x],linp);
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fat[x]&&e[i].y!=big[x]) dfs2(e[i].y,e[i].y);
}
inline void Update(int x,int y,int z){
for (;top[x]!=top[y];x=fat[top[x]]){
if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
update(1,1,n,dfn[top[x]],dfn[x],z);
}
if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
update(1,1,n,dfn[x],dfn[y],z);
}
inline signed Query(int x,int y){
int ans=0,xLc=-1,yLc=-1;
for (;top[x]!=top[y];x=fat[top[x]]){
if (dep[top[x]]<dep[top[y]]){
x^=y,y^=x,x^=y;
if (xLc^yLc) xLc^=yLc,yLc^=xLc,xLc^=yLc;
}
lL=dfn[top[x]],rR=dfn[x];
ans+=query(1,1,n,dfn[top[x]],dfn[x]);
ans-=(Rc==xLc),xLc=Lc;
}
if (dep[x]<dep[y]){
x^=y,y^=x,x^=y;
if (xLc^yLc) xLc^=yLc,yLc^=xLc,xLc^=yLc;
}
lL=dfn[y],rR=dfn[x];
ans+=query(1,1,n,dfn[y],dfn[x]);
ans-=(Rc==xLc)+(Lc==yLc);//除了x的拼接还有y的拼接
return ans;
}
signed main(){
n=iut(); m=iut();
for (rr int i=1;i<=n;++i) col[i]=iut();
for (rr int i=1;i<n;++i) add(iut(),iut());
dfs1(1,0),dfs2(1,1),build(1,1,n);
for (;m;--m){
rr char c=getchar();
while (c!='C'&&c!='Q') c=getchar();
rr int x=iut(),y=iut();
if (c=='C') Update(x,y,iut());
else print(Query(x,y)),putchar(10);
}
return 0;
}
#树链剖分,线段树#洛谷 2486 [SDOI2011]染色的更多相关文章
- 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树
正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
随机推荐
- 项目实战:Qt+OpenCV激光射击游(识别激光、识别圆)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- pinject依赖注入模块
pinject 是一个基于 Python 的轻量级依赖注入库,可以方便地实现依赖注入的功能. 下面我们将通过一个简单的示例来演示如何使用 pinject 实现依赖注入. 首先,我们需要安装 pinje ...
- gin框架中的c.Next()/c.Abort()
package main import ( "fmt" "github.com/gin-gonic/gin" ) func func1(c *gin.Conte ...
- Vue3学习(十九) - TreeSelect 树选择
写在前面 我知道自己现在的状态很不好,以为放个假能好好放松下心情,结果昨晚做梦还在工作,调试代码,和领导汇报工作. 天呐,明明是在放假,可大脑还在考虑工作的事,我的天那,这是怎么了? Vue页面参数传 ...
- 【LeetCode二叉树#11】最大二叉树(构造二叉树)
最大二叉树 力扣题目地址(opens new window) 给定一个不含重复元素的整数数组.一个以此数组构建的最大二叉树定义如下: 二叉树的根是数组中的最大元素. 左子树是通过数组中最大值左边部分构 ...
- 【Azure 存储服务】调用REST API获取Stroage Account Table中所有的Entity计数 -- Count
问题描述 在Storage Account的使用中,如果想获取Table中全部Entity的计数以及大小,如果是REST API方式,如何来获取呢? 问题解答 在Azure中,所有服务的Metrics ...
- 【Azure Developer】Python 获取 Azure 中订阅(subscription)信息,包含ID, Name等
问题描述 在Azure AD中注册一个Applicaiton后,对其进行授权,能够查看所有订阅的ReadOnly权限,然后,是否可以同通过Python代码,在完成Authorization后(使用Cl ...
- win上vscode出现undefined reference to `__imp_WSACleanup'
示例代码 #include <iostream> // 推荐加上宏定义 #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #i ...
- Kubernetes CKA考试之Killer Simulator(下)
写在前面 个人微信公众号:密码应用技术实战 个人博客园首页:https://www.cnblogs.com/informatics/ 注:学习交流使用 目录 写在前面 Question 16 | Na ...
- [VueJsDev] 基础知识 - asyncTool.js异步执行工具
[VueJsDev] 目录列表 https://www.cnblogs.com/pengchenggang/p/17037320.html asyncTool.js 异步执行工具 ::: detail ...