[CodeForces620E] New Year Tree
原题网址:http://codeforces.com/problemset/problem/620/E
啊,从这篇博客开始我就不复制题目了,毕竟大家点进来都是为了我的AC代码。
好的,这道题的题目大意就是,有一棵树,给它染色,刚开始的颜色是给定的,然后有两个操作:
1,输入v,x,将v和其所有子节点染色成x;
2,输入x,输出x的所有子节点的染色种类;
很显然,这个输入和输出的方式很有区间的味道(行家啊~
于是,我们考虑到dfs序,可以把一棵树降维到一维;
然后,我就写了一个朴素的欧拉序(节点进出的时候记录进dfs_num数组)
然后,,,我要怎么数颜色???
瞄了一眼数据范围,最多60种颜色,这明白着提醒我:放心吧,随便开数组,不会mle的~
//在教练的提醒下我选择了状压
把每种颜色作为二进制下的一位,比如(1000)2就表示这个节点有3号颜色;
区间合并的时候,就按位或一下,比如表示颜色三的(1000)和表示颜色二的(100)按位或后就是(1100)表示既有三又有二;
如果有多种颜色的时候,这种方法可以起到有效的去重(这让本打算开60个数组的我情何以堪
于是代码就出来了
漂亮得TLE了。。。
然后优化就是把欧拉序改成了前序遍历,就AC了
下面放AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define maxn 400005
using namespace std;
inline void read(int &x)
{
x=0;int 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();}
x*f;
}
inline void read(long long &x)
{
x=0;int 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();}
x*f;
}
int N,M;
long long color_v[maxn];
long long bas=1;
struct node{
int nex,to;
}edge[maxn<<2];
int head[maxn],tot;
inline void insert(int from,int to)
{
tot++;
edge[tot].nex=head[from];
head[from]=tot;
edge[tot].to=to;
}
long long st[maxn],ed[maxn],dfs_num[maxn],t;
void dfs(int x,int u)
{
//cout<<"dfs note: "<<x<<" "<<t<<endl;
//cout<<x<<" ";
st[x]=++t;
dfs_num[t]=color_v[x];
for(int i=head[x];i;i=edge[i].nex)
{
if(edge[i].to!=u)
{
dfs(edge[i].to,x);
}
}
ed[x]=t;
//cout<<x<<" ";
}
struct tree{
int l,r;
long long color;
}tree[maxn<<4];
int bit(long long i)
{
int ans=0;
while(i)
{
ans+=i&1;
i>>=1;
}
return ans;
}
void push_up(int rt)
{
tree[rt].color=tree[rt<<1].color|tree[rt<<1|1].color;
}
void push_down(int rt)
{
tree[rt<<1].color=tree[rt].color;
tree[rt<<1|1].color=tree[rt].color;
}
void build(int rt,int l,int r)
{
tree[rt].l=l;
tree[rt].r=r;
if(l==r)
{
tree[rt].color=bas<<dfs_num[l];
return ;
}
int mid=l+r>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
push_up(rt);
}
void update(int rt,int l,int r,int col)
{
if(tree[rt].l>r||tree[rt].r<l)
return ;
if(tree[rt].l>=l&&tree[rt].r<=r)
{
tree[rt].color=bas<<col;
return ;
}
if(bit(tree[rt].color)==1)
push_down(rt);
int mid=tree[rt].l+tree[rt].r>>1;
if(l<=mid)
update(rt<<1,l,r,col);
if(r>mid)
update(rt<<1|1,l,r,col);
push_up(rt);
}
long long query(int rt,int l,int r)
{
if(tree[rt].l>r||tree[rt].r<l)
return 0;
if(tree[rt].l>=l&&tree[rt].r<=r)
{
return tree[rt].color;
}
if(tree[rt].l==tree[rt].r)
return 0;
if(bit(tree[rt].color)==1)
push_down(rt);
int mid=tree[rt].l+tree[rt].r>>1;
long long ans=0;
if(l<=mid)
{
ans|=query(rt<<1,l,r);
}
/*if(ans==(1<<23))
cout<<"LEFT ERROR: "<<tree[rt].l<<" "<<tree[rt].r<<endl;*/
if(r>mid)
{
ans|=query(rt<<1|1,l,r);
}
return ans;
}
/*void search(long long rt)
{
if(bit(tree[rt].color)==1)
{
for(long long i=tree[rt].l;i<=tree[rt].r;i++)
cout<<log2(tree[rt].color)<<" ";
return ;
}
search(rt<<1);
search(rt<<1|1);
}*/
int main()
{
read(N);read(M);
for(int i=1;i<=N;i++)
{
read(color_v[i]);
}
int u;
int v;
for(int i=1;i<N;i++)
{
read(u);read(v);
insert(u,v);
insert(v,u);
}
//cout<<"dfs note: ";
dfs(1,1);
//cout<<endl;
build(1,1,t);
int op;
for(int i=1;i<=M;i++)
{
//cout<<"lin note: ";
//search(1);
//cout<<endl;
read(op);
if(op==1)
{
read(u);read(v);
update(1,st[u],ed[u],v);
}
else
{
read(u);
//cout<<"check :"<<st[u]<<" "<<ed[u]<<endl;
printf("%d\n",bit(query(1,st[u],ed[u])));
}
}
}
/*
10 10
23 25 23 42 23 53 49 40 28 44
1 7
1 2
2 4
4 10
8 10
6 8
3 8
5 3
9 5
2 10
1 6 52
1 8 43
2 3
*/