隐藏页面特效

2243: [SDOI2011]染色

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 6904  Solved: 2562
[Submit][Status][Discuss]

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,表示xy之间有一条无向边。

下面 行每行描述一个操作:

“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]之间。

 

Source

/* 维护: lcol(当前区间左端点的颜色) rcol(当前区间右端点的颜色) sum(当前区间颜色段数量) 合并: sum=lson.sum+rson.sum-1{lson.rcol==rson.lcol} sum=lson.sum+rson.sum{lson.rcol!=rson.lcol} */ #include<cstdio> #include<iostream> #define lc k<<1 #define rc k<<1|1 #define O3 __attribute__((optimize("O3"))) #define IN inline using namespace std; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } char in(){ for(char ch=getchar();;ch=getchar()) if(ch>='A'&&ch<='Z') return ch; } const int M=1e5+5,N=M<<2; struct sgt{int lcol,rcol,sum,tag;}tr[N]; struct edge{int v,next;}e[N]; int n,m,tot,cnt,head[M],pos[M],dfn[M],val[M],son[M],top[M],dep[M],fa[M],siz[M]; IN void add(int x,int y){ e[++tot].v=y;e[tot].next=head[x];head[x]=tot; e[++tot].v=x;e[tot].next=head[y];head[y]=tot; } O3 void dfs(int x,int f,int de){ fa[x]=f;dep[x]=de;siz[x]=1; for(int i=head[x];i;i=e[i].next){ if(e[i].v!=f){ dfs(e[i].v,x,de+1); siz[x]+=siz[e[i].v]; if(!son[x]||siz[son[x]]<siz[e[i].v]) son[x]=e[i].v; } } } O3 void getpos(int x,int t1){ top[x]=t1;pos[x]=++cnt;dfn[cnt]=x; if(!son[x]) return ; getpos(son[x],t1); for(int i=head[x];i;i=e[i].next){ if(son[x]!=e[i].v&&fa[x]!=e[i].v){ getpos(e[i].v,e[i].v); } } } //=====================================================预处理 IN void updata(int k){ tr[k].lcol=tr[lc].lcol; tr[k].rcol=tr[rc].rcol; tr[k].sum=tr[lc].sum+tr[rc].sum-(tr[lc].rcol==tr[rc].lcol); } IN void pushdown(int k){ if(!tr[k].tag) return ; tr[lc].lcol=tr[lc].rcol=tr[k].tag; tr[rc].lcol=tr[rc].rcol=tr[k].tag; tr[lc].tag=tr[rc].tag=tr[k].tag; tr[lc].sum=tr[rc].sum=1; tr[k].tag=0; } O3 void build(int k,int l,int r){ if(l==r){ tr[k].lcol=tr[k].rcol=val[dfn[l]]; tr[k].sum=1; return ; } int mid=l+r>>1; build(lc,l,mid); build(rc,mid+1,r); updata(k); } O3 void change(int k,int l,int r,int x,int y,int v){ if(l==x&&r==y){ tr[k].sum=1; tr[k].lcol=tr[k].rcol=tr[k].tag=v; return ; } int mid=l+r>>1; pushdown(k); if(y<=mid) change(lc,l,mid,x,y,v); else if(x>mid) change(rc,mid+1,r,x,y,v); else change(lc,l,mid,x,mid,v),change(rc,mid+1,r,mid+1,y,v); updata(k); } O3 int query(int k,int l,int r,int x,int y){ if(l==x&&r==y) return tr[k].sum; pushdown(k); int mid=l+r>>1; if(y<=mid) return query(lc,l,mid,x,y); else if(x>mid) return query(rc,mid+1,r,x,y); else{ int res=query(lc,l,mid,x,mid)+query(rc,mid+1,r,mid+1,y); if(tr[lc].rcol==tr[rc].lcol) res--; return res; } } O3 int ask_l(int k,int l,int r,int x){ if(l==r) return tr[k].lcol; pushdown(k); int mid=l+r>>1; if(x<=mid) return ask_l(lc,l,mid,x); else return ask_l(rc,mid+1,r,x); } //=====================================================线段树 IN void modify(int x,int y,int c){ for(;top[x]!=top[y];x=fa[top[x]]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); change(1,1,n,pos[top[x]],pos[x],c); } //if(x==y) return ;1W if(dep[x]>dep[y]) swap(x,y); change(1,1,n,pos[x],pos[y],c); } IN int find(int x,int y){ int nc,fc,ans=0; for(;top[x]!=top[y];x=fa[top[x]]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); ans+=query(1,1,n,pos[top[x]],pos[x]); nc=ask_l(1,1,n,pos[top[x]]); fc=ask_l(1,1,n,pos[fa[top[x]]]); if(nc==fc) ans--; } //if(x==y) return ans;2W if(dep[x]>dep[y]) swap(x,y); ans+=query(1,1,n,pos[x],pos[y]); if(!ans) ans++; return ans; } //=====================================================树链剖分 int main(){ n=read();m=read(); for(int i=1;i<=n;i++) val[i]=read(); for(int i=1,x,y;i<n;i++){ x=read();y=read(); add(x,y); } dfs(1,1,1); getpos(1,1); build(1,1,n); for(int i=1,a,b,c;i<=m;i++){ c=in(); if(c=='C'){ a=read();b=read();c=read(); modify(a,b,c); } else{ a=read();b=read(); printf("%d\n",find(a,b)); } } return 0; }

 


__EOF__

本文作者shenben
本文链接https://www.cnblogs.com/shenben/p/6362831.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   神犇(shenben)  阅读(217)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示