版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37129433/article/details/82598103
New Year Tree
题 意:给你一棵节点个数为n的树,有q个操作,1. x y把x以及x的子树全部染成y颜色。
2.l,r 查询区间l,r有多少种不同的颜色。
数据范围:
1<=n,m<=4e5+5;
1<=l<=r<=n
1<=y<=60
输入样例:
7 10
1 1 1 1 1 1 1
1 2
1 3
1 4
3 5
3 6
3 7
1 3 2
2 1
1 4 3
2 1
1 2 5
2 1
1 6 4
2 1
2 2
2 3
输出样例:
2
3
4
5
1
2
思 路:dfs序维护的是对子树的操作,那么就是怎么处理不同的颜色,发现才60种颜色,用二进制状压一下,范围不会超过long long。然后就又编程dfs序+线段树的一道简单题了
#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int maxn = 4e5+5;
struct node {
int to;
int next;
} G[2*maxn];
int head[maxn];
ll sum[maxn<<2],lazy[maxn<<2];
int out[maxn],in[maxn];
int cnt,total;
int a[maxn];
int n,m;
void init() {
cnt = 0;
total=0;
memset(out,0,sizeof(out));
memset(in,0,sizeof(in));
memset(sum,0,sizeof(sum));
memset(lazy,0,sizeof(lazy));
memset(head,-1,sizeof(head));
}
void add(int u,int v) {
G[total].to = v;
G[total].next = head[u];
head[u] = total++;
}
void dfs(int u,int fa) {
in[u]=++cnt;
for(int i=head[u]; i!=-1; i=G[i].next) {
int to = G[i].to;
if(to==fa)continue;
dfs(to,u);
}
out[u]=cnt;
}
void PushUp(int rt) {
sum[rt] = (sum[rt<<1] | sum[rt<<1|1]);
}
void PushDown(int rt) {
if(lazy[rt]) {
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
sum[rt<<1] = sum[rt<<1|1] = lazy[rt];
lazy[rt] = 0;
}
}
void update(int L,int R,int x,int l,int r,int rt) {
if(L<=l && r<=R) {
sum[rt] = (1ll<<x);
lazy[rt] = (1ll<<x);
return ;
}
PushDown(rt);
int m = (l+r)/2;
if(L<=m)update(L,R,x,lson);
if(R>m) update(L,R,x,rson);
PushUp(rt);
}
ll query(int L,int R,int l,int r,int rt) {
if(L<=l && r<=R) {
return sum[rt];
}
int m = (l+r)/2;
ll ans = 0;
PushDown(rt);
if(L<=m) ans|=query(L,R,lson);
if(R>m) ans|=query(L,R,rson);
return ans;
}
int main() {
while(~scanf("%d %d",&n,&m)) {
init();
for(int i=1; i<=n; i++)scanf("%d",&a[i]);
int u,v;
for(int i=1; i<=n-1; i++) {
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,-1);
for(int i=1; i<=n; i++) {
int l = in[i],r=in[i];
update(l,r,a[i],1,n,1);
}
int ch,x,y;
while(m--) {
scanf("%d",&ch);
if(ch == 1) {
scanf("%d %d",&x,&y);
int l = in[x],r = out[x];
update(l,r,y,1,n,1);
} else {
scanf("%d",&x);
int l = in[x],r = out[x];
ll ans = query(l,r,1,n,1);
int res = 0;
for(int i=0;i<62;i++){
if((1ll<<i) & ans)res++;
}
printf("%d\n",res);
}
}
}
return 0;
}