2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 10391 Solved: 3987
[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]之间。
Source
回头一想,这个题还是蛮简单的,就是一个pushdown 中的一个小小的错误。。TMD 找了我一晚上!!!!
做法简单来说就是在树链上向上蹦的时候,我们分别考虑x和y 然后判断有没有颜色相邻的情况,有则减1.
代码:
#include<bits/stdc++.h>
#define lson (i<<1)
#define rson (i<<1|1)
using namespace std;
typedef long long ll;
const int N =1e5+5;
struct eee
{
int v,next;
}edge[N*2];
int tot,head[N];
int dep[N];
int fat[N];
int rak[N];
int idd[N];
int top[N];
int son[N];
int siz[N];
int cnt;
int cc[N];
int n,m;
struct node
{
int l,r;
int lcol,rcol;
int col;
int cnt;
int lz;
}tr[N<<2];
void init()
{
tot=0;
memset(head,-1,sizeof(head));
memset(son,0,sizeof(son));
memset(siz,0,sizeof(siz));
}
void add(int u,int v)
{
edge[++tot].v=v; edge[tot].next=head[u]; head[u]=tot;
}
void dfs1(int u,int fa,int deep)
{
fat[u]=fa;
dep[u]=deep;
siz[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue;
dfs1(v,u,deep+1);
siz[u]+=siz[v];
if(son[u]==0||siz[v]>siz[son[u]]){
son[u]=v;
}
}
}
void dfs2(int u,int t)
{
top[u]=t;
idd[u]=++cnt;
rak[cnt]=u;
if(!son[u]) return ;
dfs2(son[u],t);
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v!=son[u]&&v!=fat[u]){
dfs2(v,v);
}
}
}
void push_up(int i)
{
int ll,lr,rl,rr;
ll=tr[lson].lcol; lr=tr[lson].rcol; rl=tr[rson].lcol; rr=tr[rson].rcol;
if(lr==rl){
tr[i].cnt=tr[lson].cnt+tr[rson].cnt-1;
}
else tr[i].cnt=tr[lson].cnt+tr[rson].cnt;
tr[i].lcol=ll;tr[i].rcol=rr;
}
void push_down(int i)
{
if(tr[i].lz){
int &lz=tr[i].lz;
tr[lson].lz=lz;
tr[lson].col=tr[lson].lcol=tr[lson].rcol=lz;
tr[lson].cnt=1;
tr[rson].lz=lz;
tr[rson].col=tr[rson].lcol=tr[rson].rcol=lz;
tr[rson].cnt=1;
lz=0;
}
}
void build(int i,int l,int r)
{
tr[i].l=l; tr[i].r=r; tr[i].col=0;
tr[i].lcol=tr[i].rcol=0; tr[i].lz=0;
if(l==r){
tr[i].col=tr[i].lcol=tr[i].rcol=cc[rak[l]];
tr[i].cnt=1;
return ;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
push_up(i);
}
void update(int i,int l,int r,int c)
{
if(tr[i].l==l&&tr[i].r==r){
tr[i].lz=c;
tr[i].col=tr[i].lcol=tr[i].rcol=c;
tr[i].cnt=1;
return ;
}
push_down(i);
int mid=(tr[i].l+tr[i].r)>>1;
if(r<=mid) update(lson,l,r,c);
else if(l>mid) update(rson,l,r,c);
else{
update(lson,l,mid,c);
update(rson,mid+1,r,c);
}
push_up(i);
}
int query(int i,int l,int r,int &ll,int &rr)
{
if(tr[i].l==l&&tr[i].r==r){
ll=tr[i].lcol; rr=tr[i].rcol;
//cout<<"colcolcol "<<ll<<" "<<rr<<endl;
return tr[i].cnt;
}
push_down(i);
int mid=(tr[i].l+tr[i].r)>>1;
if(r<=mid) return query(lson,l,r,ll,rr);
else if(l>mid) return query(rson,l,r,ll,rr);
else{
int aa,bb,cc,dd;
int cnt1,cnt2;
cnt1=query(lson,l,mid,aa,bb);
cnt2=query(rson,mid+1,r,cc,dd);
ll=aa; rr=dd;
if(bb==cc) return cnt1+cnt2-1;
else return cnt1+cnt2;
}
}
void updates(int x,int y,int c)
{
int fx=top[x]; int fy=top[y];
while(fx!=fy)
{
if(dep[fx]>=dep[fy]){
//cout<<"ll "<<idd[fx]<<" rr "<<idd[x]<<endl;
update(1,idd[fx],idd[x],c);
x=fat[fx];
}
else{
//cout<<"ll "<<idd[fx]<<" rr "<<idd[x]<<endl;
update(1,idd[fy],idd[y],c);
y=fat[fy];
}
fx=top[x];
fy=top[y];
}
//cout<<" ll "<<idd[x]<<" rr "<<idd[y]<<endl;
if(idd[x]<=idd[y]) update(1,idd[x],idd[y],c);
else update(1,idd[y],idd[x],c);
}
int getsums(int x,int y)
{
int ans=0;
int cnt,precnt;
int aa,bb,cc,dd; /// 跳 x
int aaa,bbb,ccc,ddd; /// 跳 y
int fx=top[x],fy=top[y];
aa=bb=cc=dd=0;
aaa=bbb=0;
while(fx!=fy)
{
if(dep[fx]>=dep[fy]){
ans+=query(1,idd[fx],idd[x],cc,dd);
if(dd==aa) ans--;
aa=cc; bb=dd;
x=fat[fx]; fx=top[x];
}
else{
ans+=query(1,idd[fy],idd[y],ccc,ddd);
if(ddd==aaa) ans--;
aaa=ccc; bbb=ddd;
y=fat[fy]; fy=top[y];
}
}
if(idd[x]<=idd[y]){
ans+=query(1,idd[x],idd[y],cc,dd);
if(cc==aa) ans--;
if(dd==aaa) ans--;
}
else{
ans+=query(1,idd[y],idd[x],ccc,ddd);
if(ccc==aaa) ans--;
if(ddd==aa) ans--;
}
return ans;
}
int main()
{
int u,v,c;
char op[5];
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&cc[i]);
for(int i=1;i<=n;i++) cc[i]++;
init();
for(int i=1;i<n;i++){
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
}
dfs1(1,1,0);
dfs2(1,1);
build(1,1,n);
//cout<<tr[1].cnt<<endl;
while(m--)
{
scanf("%s",op);
if(op[0]=='Q'){
scanf("%d %d",&u,&v);
int ans=getsums(u,v);
printf("%d\n",ans);
}
else{
scanf("%d %d %d",&u,&v,&c);
c++;
updates(u,v,c);
}
}
return 0;
}
/*
6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
*/