您的位置:首页 > 其它

AC日记——[SDOI2011]染色 洛谷 P2486

2017-02-04 10:30 381 查看

题目描述



输入输出格式

输入格式:



输出格式:

对于每个询问操作,输出一行答案。

输入输出样例

输入样例#1:

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


输出样例#1:

3
1
2


说明





思路:

  树剖+线段树维护区间颜色数量

来,上代码:

#include <cstdio>
#include <iostream>
#include <algorithm>

#define maxn 200001

using namespace std;

struct TreeNodeType {
int l,r,dis,lc,rc,flag,mid;
};
struct TreeNodeType tree[maxn<<2];

struct EdgeType {
int to,next;
};
struct EdgeType edge[maxn<<1];

int n,m,if_z,dis[maxn],flag[maxn],dis_[maxn];
int size[maxn],head[maxn],deep[maxn],f[maxn];
int cnt,tot,num,belong[maxn];

char Cget;

inline void read_int(int &now)
{
now=0,if_z=1,Cget=getchar();
while(Cget>'9'||Cget<'0')
{
if(Cget=='-') if_z=-1;
Cget=getchar();
}
while(Cget>='0'&&Cget<='9')
{
now=now*10+Cget-'0';
Cget=getchar();
}
now*=if_z;
}

inline void edge_add(int from,int to)
{
edge[++num].to=from,edge[num].next=head[to],head[to]=num;
edge[++num].to=to,edge[num].next=head[from],head[from]=num;
}

void search(int now,int fa)
{
int pos=cnt++;
deep[now]=deep[fa]+1,f[now]=fa;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==fa) continue;
search(edge[i].to,now);
}
size[now]=cnt-pos;
}

void search_(int now,int chain)
{
belong[now]=chain,flag[now]=++cnt;
dis_[flag[now]]=dis[now];
int pos=0;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==f[now]) continue;
if(size[edge[i].to]>size[pos]) pos=edge[i].to;
}
if(pos!=0) search_(pos,chain);
else return ;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==f[now]||edge[i].to==pos) continue;
search_(edge[i].to,edge[i].to);
}
}

inline void tree_up(int now)
{
if(tree[now<<1].rc==tree[now<<1|1].lc)
{
tree[now].dis=tree[now<<1].dis+tree[now<<1|1].dis-1;
}
else
{
tree[now].dis=tree[now<<1].dis+tree[now<<1|1].dis;
}
tree[now].lc=tree[now<<1].lc,tree[now].rc=tree[now<<1|1].rc;
}

inline void tree_down(int now)
{
if(tree[now].l==tree[now].r) return ;
tree[now<<1].dis=1,tree[now<<1|1].dis=1;
tree[now<<1].lc=tree[now<<1].rc=tree[now].flag;
tree[now<<1|1].lc=tree[now<<1|1].rc=tree[now].flag;
tree[now<<1].flag=tree[now<<1|1].flag=tree[now].flag;
tree[now].flag=0;
}

void tree_build(int now,int l,int r)
{
tree[now].l=l,tree[now].r=r;
if(l==r)
{
tree[now].lc=dis_[++cnt];
tree[now].rc=tree[now].lc;
tree[now].dis=1;
return ;
}
tree[now].mid=(l+r)>>1;
tree_build(now<<1,l,tree[now].mid);
tree_build(now<<1|1,tree[now].mid+1,r);
tree_up(now);
}

void tree_change(int now,int l,int r,int x)
{
if(tree[now].l==l&&tree[now].r==r)
{
tree[now].dis=1,tree[now].flag=x;
tree[now].lc=tree[now].rc=x;
return ;
}
if(tree[now].flag) tree_down(now);
if(l>tree[now].mid) tree_change(now<<1|1,l,r,x);
else if(r<=tree[now].mid) tree_change(now<<1,l,r,x);
else
{
tree_change(now<<1,l,tree[now].mid,x);
tree_change(now<<1|1,tree[now].mid+1,r,x);
}
tree_up(now);
}

int tree_query(int now,int l,int r)
{
if(tree[now].l==l&&tree[now].r==r)
{
return tree[now].dis;
}
if(tree[now].flag) tree_down(now);
tree_up(now);
if(l>tree[now].mid) return tree_query(now<<1|1,l,r);
else if(r<=tree[now].mid) return tree_query(now<<1,l,r);
else
{
int ld=tree_query(now<<1,l,tree[now].mid);
int rd=tree_query(now<<1|1,tree[now].mid+1,r);
if(tree[now<<1].rc==tree[now<<1|1].lc) return ld+rd-1;
else return ld+rd;
}
}

int tree_query_color(int now,int to)
{
if(tree[now].l==tree[now].r&&tree[now].l==to)
{
return tree[now].lc;
}
if(tree[now].flag) tree_down(now);
tree_up(now);
if(to>tree[now].mid) return tree_query_color(now<<1|1,to);
else return tree_query_color(now<<1,to);
}

inline void solve_change(int x,int y,int z)
{
while(belong[x]!=belong[y])
{
if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
tree_change(1,flag[belong[x]],flag[x],z);
x=f[belong[x]];
}
tree_change(1,min(flag[x],flag[y]),max(flag[x],flag[y]),z);
}

inline int solve_query(int x,int y)
{
int ans=0;
while(belong[x]!=belong[y])
{
if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
ans+=tree_query(1,flag[belong[x]],flag[x]);
if(tree_query_color(1,flag[belong[x]])==tree_query_color(1,flag[f[belong[x]]])) ans--;
x=f[belong[x]];
}
ans+=tree_query(1,min(flag[x],flag[y]),max(flag[x],flag[y]));
return ans;
}

int main()
{
read_int(n),read_int(m);
for(int i=1;i<=n;i++) read_int(dis[i]);
int from,to,pos;
for(int i=1;i<n;i++)
{
read_int(from),read_int(to);
edge_add(from,to);
}
search(1,0),cnt=0,search_(1,1),cnt=0,tree_build(1,1,n);
char type;
for(int i=1;i<=m;i++)
{
cin>>type;
if(type=='C')
{
read_int(from),read_int(to),read_int(pos);
solve_change(from,to,pos);
}
else
{
read_int(from),read_int(to);
printf("%d\n",solve_query(from,to));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: