博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HYSBZ - 2243 染色 (树链剖分+线段树)
阅读量:4691 次
发布时间:2019-06-09

本文共 2612 字,大约阅读时间需要 8 分钟。

题意:树上每个结点有自己的颜色,支持两种操作:1.将u到v路径上的点颜色修改为c; 2.求u到v路径上有多少段不同的颜色。

分析:树剖之后用线段树维护区间颜色段数。区间查询区间修改。线段树结点中维护的有:段数,左端点颜色,右端点颜色和懒惰标记。

当区间合并时,若左孩子的右端点颜色和右孩子的左端点颜色相同,那么段数要减1。

区间修改时注意维护左右端点的颜色。

查询时若左右子区间连接处的颜色相同,段数减1。

在两点向一条链上寻找LCA时,每次查询都要保存该条链顶端的颜色,若该链顶端的颜色与下次查询的右端点相同,那么段数减1。

最后当两点回溯到一条链上之后,若两点对应各自上次回溯链顶端的颜色是否与查询区间的左右端点相同,则答案都需减1。

#include
#include
#include
#include
#define lson rt<<1#define rson rt<<1|1#define Lson l,m,lson#define Rson m+1,r,rsontypedef long long LL;using namespace std;const int maxn =1e5+5;struct Edge{ int to,next;}E[2*maxn];int n,head[maxn],tot;int cnt,idx,size[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],id[maxn],rnk[maxn];int a[maxn];void init(){ cnt=idx=tot=0; memset(head,-1,sizeof(head)); dep[1]=0,fa[1]=1,size[0]=0; memset(son,0,sizeof(son));}void AddEdge(int u,int v){ E[tot] = (Edge){v,head[u]}; head[u]=tot++;}void dfs1(int u){ size[u]=1; for(int i=head[u];~i;i=E[i].next){ int v=E[i].to; if(v!=fa[u]){ fa[v]=u; dep[v]=dep[u]+1; dfs1(v); size[u]+=size[v]; if(size[son[u]]
>1; build(Lson); build(Rson); pushup(rt);}void update(int L,int R,int col,int l=1,int r=n,int rt=1){ if(L<=l && R>=r){ tree[rt].sum = tree[rt].add =1; tree[rt].lc = tree[rt].rc = col; return ; } pushdown(l,r,rt); int m =(l+r)>>1; if(L<=m) update(L,R,col,Lson); if(R>m) update(L,R,col,Rson); pushup(rt);}int query(int L,int R,int l=1,int r=n,int rt=1){ //单点 if(L==l) Lc = tree[rt].lc; if(R==r) Rc = tree[rt].rc; if(L<=l && R>=r) return tree[rt].sum; pushdown(l,r,rt); int m = (l+r)>>1 , ans=0; bool left = false; if(L<=m) { ans+=query(L,R,Lson); left = true; } if(R>m){ ans +=query(L,R,Rson); if(left && tree[lson].rc ==tree[rson].lc) ans--; } pushup(rt); return ans;}void CHANGE(int u,int v,int col){ while(top[u]!=top[v]){ if(dep[top[u]]
dep[v]) swap(u,v); update(id[u],id[v],col);}int Qsum(int u,int v){ int c1=-1,c2=-1, ans=0; //记录上条链最左侧的颜色 while(top[u]!=top[v]){ if(dep[top[u]]
dep[v]){swap(u,v);swap(c1,c2);} ans += query(id[u],id[v]); if(Lc==c1) ans--; if(Rc==c2) ans--; return ans; }int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif int m,q,u,v; char op[5]; while(scanf("%d%d",&n,&m)==2){ init(); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i

 

转载于:https://www.cnblogs.com/xiuwenli/p/9496846.html

你可能感兴趣的文章
Oracle学习之常见错误整理
查看>>
lock_sga引起的ksvcreate :process(m000) creation failed
查看>>
数据库插入数据乱码问题
查看>>
OVER(PARTITION BY)函数用法
查看>>
altium annotate 选项设置 complete existing packages
查看>>
【模式识别与机器学习】——SVM举例
查看>>
【转】IT名企面试:微软笔试题(1)
查看>>
IO流入门-第十章-DataInputStream_DataOutputStream
查看>>
DRF的分页
查看>>
Mysql 模糊匹配(字符串str中是否包含子字符串substr)
查看>>
python:open/文件操作
查看>>
流程控制 Day06
查看>>
Linux下安装Tomcat
查看>>
windows live writer 2012 0x80070643
查看>>
tomcat 和MySQL的安装
查看>>
11.5 内部类
查看>>
Cosine Similarity
查看>>
halt和shutdown 的区别
查看>>
git常用操作
查看>>
京东SSO单点登陆实现分析
查看>>