2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 7964 Solved: 2987
[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,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“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]之间。
题解:树链剖分+线段树,注意每次查询时查询的是断断续续的区间,所以每次要继续下上一次区间的信息,如果两次区间的始末位置颜色相同的话,合并之后的颜色数就要-1。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N = 200010;
int n,m;
int a[N],co[N];
struct node{
int pre,v;
}edge[N];
int num=0,head[N];
void addedge(int from,int to){
num++;
edge[num].pre=head[from];
edge[num].v=to;
head[from]=num;
}
int fa[N],dep[N];
int siz[N],son[N];
void dfs1(int u,int f,int d){
siz[u]=1,fa[u]=f,dep[u]=d;
for(int i=head[u];i;i=edge[i].pre){
int v=edge[i].v;
if(v==f) continue;
dfs1(v,u,d+1);
siz[u]+=siz[v];
if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v;
}
}
int indx=0;
int in[N],out[N],top[N];
void dfs2(int u,int tp){
in[u]=out[u]=++indx;
co[indx]=a[u];
top[u]=tp;
if(son[u]==-1) return ;
dfs2(son[u],tp);
for(int i=head[u];i;i=edge[i].pre){
int v=edge[i].v;
if(v==son[u]||v==fa[u]) continue;
dfs2(v,v);
}
out[u]=indx;
}
struct Node{
int ans;
int lx,rx;
int l,r;
int flag;
}t[N<<4];
void update(int root){
if(t[root<<1].rx==t[root<<1|1].lx)
t[root].ans=t[root<<1].ans+t[root<<1|1].ans-1;
else t[root].ans=t[root<<1].ans+t[root<<1|1].ans;
t[root].lx=t[root<<1].lx,t[root].rx=t[root<<1|1].rx;
}
void build(int root,int l,int r){
t[root].l=l,t[root].r=r,t[root].flag=0;
if(l==r){
t[root].ans=1;
t[root].lx=t[root].rx=co[l];
return ;
}
int mid=l+r>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
update(root);
}
void pushdown(int root){
int flag=t[root].flag,l=t[root].l,r=t[root].r;
if(flag){
t[root<<1].ans=t[root<<1|1].ans=1;
t[root<<1].lx=t[root<<1].rx=flag;
t[root<<1|1].lx=t[root<<1|1].rx=flag;
t[root<<1].flag=t[root<<1|1].flag=flag;
t[root].flag=0;
}
}
void modify(int root,int pos,int val,int delta){
int l=t[root].l,r=t[root].r;
if(pos<=l&&val>=r){
t[root].ans=1;
t[root].lx=t[root].rx=delta;
t[root].flag=delta;
return ;
}
int mid=l+r>>1;
pushdown(root);
if(pos<=mid) modify(root<<1,pos,val,delta);
if(val>mid) modify(root<<1|1,pos,val,delta);
update(root);
}
void modify(int u,int v,int delta){
int f1=top[u],f2=top[v];
while(f1!=f2){
if(dep[f1]<dep[f2]) swap(f1,f2),swap(u,v);
modify(1,in[f1],in[u],delta);
u=fa[f1],f1=top[u];
}
if(dep[u]>dep[v]) swap(u,v);
modify(1,in[u],in[v],delta);
}
int lc,rc;
int query(int root,int pos,int val,int L,int R){
int l=t[root].l,r=t[root].r;
if(l==L) lc=t[root].lx;
if(r==R) rc=t[root].rx;
if(pos==l&&val==r) return t[root].ans;
int mid=l+r>>1;
pushdown(root);
if(val<=mid) return query(root<<1,pos,val,L,R);
else if(pos>mid) return query(root<<1|1,pos,val,L,R);
else{
int a=query(root<<1,pos,mid,L,R);
int b=query(root<<1|1,mid+1,val,L,R);
if(t[root<<1|1].lx==t[root<<1].rx) return a+b-1;
else return a+b;
}
}
int query(int u,int v){
int f1=top[u],f2=top[v];
int sum=0;
int co1=-1,co2=-1;
while(f1!=f2){
if(dep[f1]<dep[f2]) swap(f1,f2),swap(u,v),swap(co1,co2);
sum+=query(1,in[f1],in[u],in[f1],in[u]);
if(rc==co1) sum--;
co1=lc;
u=fa[f1];
f1=top[u];
}
if(dep[u]<dep[v]) swap(u,v),swap(co1,co2);
sum+=query(1,in[v],in[u],in[v],in[u]);
if(rc==co1) sum--;if(lc==co2) sum--;
return sum;
}
#define ms(x,y) memset(x,y,sizeof(x))
int main(){
ms(son,-1);
scanf("%d%d",&n,&m);
for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
for(register int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);addedge(v,u);
}
dfs1(1,0,0);dfs2(1,1);
build(1,1,n);
while(m--){
char s[10];
int u,v,delta;
scanf("%s",s);
if(s[0]=='C'){
scanf("%d%d%d",&u,&v,&delta);
modify(u,v,delta);
}
else{
scanf("%d%d",&u,&v);
printf("%d\n",query(u,v));
}
}
return 0;
}
7月60篇博客达成。这个月真是勤勉。