Description
农场下雪啦!Bessie 和往年开冬一样在堆雪牛。她之前是个写实派,总是想把他的雪牛堆得和个真牛一样。但今年不一样,受到来自东方的神秘力量的影响,他想来点抽象艺术,因此他想堆成一棵树的样子。这棵树由 个雪球, 根树枝构成,每根树枝连接两个雪球,并且每两个雪球之间路径唯一。
Bessie 要给他的雪牛来点细节。因此他给其中一个雪球加了个鼻子,来表示这是他那抽象的牛的头,并且把它称作雪球 。为了让雪牛更好看,他还要给某些雪球来点不同的颜色。于是,他用旧牛奶桶装满了颜料泼到雪牛上。这些颜料分别被编号为 ,且每种颜色都无限量供应。
当 Bessie 把一桶颜料泼到一个雪球上时,这个雪球子树上的所有雪球也会被染色(我们称雪球 在雪球 的子树里当且仅当雪球 处在雪球 到雪球 的路径上)。Bessie 有着精确的泼颜料技术,因此在泼完一种颜料后,一个雪球上之前被染过的所有颜色依然清晰可见。例如,一个雪球之前显现出来颜色 ,然后 Bessie 把装有 号颜色的牛奶桶泼上去,那么这个雪球将显现出来颜色 。 在泼了几桶颜料以后,Bessie 可能想要了解它的雪牛有多五彩斑斓。令雪球 的『颜色丰富度』为这个雪球被染上的不同颜色总数 ,当 Bessie 想了解雪球 的相关信息时,你应该回答他雪球 的子树中所有的雪球的颜色丰富度之和。
救救孩子吧!
Input
第一行,
N
N
N 和询问数
Q
Q
Q。
接下来 N − 1 N-1 N−1 行每行两个用空格隔开的数 a a a 和 b b b,表示雪球 a a a和 b b b中间有一根树枝相连。
最后 q q q行每行一个请求,格式及对应含义如下:
1
x
c
1~x~c
1 x c(修改):表示 Bessie 把一桶装有颜色
c
c
c 的颜料泼到雪球
x
x
x ,使得其子树上所有雪球被染色。
2
x
2~x
2 x(询问):询问雪球
x
x
x 的子树的颜色丰富度之和。
Output
对于每个询问,输出所询问子树的颜色丰富度之和。为了防止溢出,你需要使用 64 位整数。
Examples
Input
5 18
1 2
1 3
3 4
3 5
1 4 1
2 1
2 2
2 3
2 4
2 5
1 5 1
2 1
2 2
2 3
2 4
2 5
1 1 1
2 1
2 2
2 3
2 4
2 5
Output
1
0
1
1
0
2
0
2
1
1
5
1
3
1
1
Note
1
≤
N
,
Q
,
c
≤
1
0
5
,
1
≤
a
,
b
,
x
≤
N
1 \leq N, Q, c \leq 10^5, 1 \leq a,b,x \leq N
1≤N,Q,c≤105,1≤a,b,x≤N
Souce
LibreOJ 3227
USACO 2019 December Contest, Platinum
Solution
对每种颜色维护一个Set,存放已经染上这种颜色的子树区间
如果只有对子树区间的修改,容易发现每次修改的区间要么相互包含,要么就没有交集
所以修改区间[L,R] 时,在对应颜色的Set中将包含于其的区间的贡献删除,再添加上该区间的贡献
套上树状数组区间修改/查询
Code
#include <bits/stdc++.h>
#define P pair<int,int>
using namespace std;
const int maxn = 2e5 + 7;
inline int lowbit(int x){return x & (-x);}
int n;
ll bit1[maxn<<1],bit2[maxn<<1];
void modify(ll bit[] ,int pos,int k){
while(pos <= n) bit[pos] += k, pos += lowbit(pos);
}
ll query(ll bit[], int pos){
ll res = 0;
while(pos) res += bit[pos], pos -= lowbit(pos);
return res;
}
void modify(int l,int r,int k){
modify(bit1,l,k); modify(bit1,r+1,-k);
modify(bit2,l,k*l); modify(bit2,r+1,-k*(r+1));
}
ll query(int l,int r){
return (query(bit1,r) * (r+1) - query(bit2,r)) - (query(bit1,l-1)*l - query(bit2,l-1));
}
int ecnt,head[maxn<<1];
struct Edge{
int v,next;
}e[maxn << 1];
void add(int u,int v){
e[++ecnt] = (Edge) {v,head[u]}, head[u] = ecnt;
e[++ecnt] = (Edge) {u,head[v]}, head[v] = ecnt;
}
int cnt,dfn[maxn],low[maxn];
void dfs(int u,int fa){
dfn[u] = ++cnt;
for(int i = head[u];i;i = e[i].next){
int v = e[i].v;if(v == fa) continue;
dfs(v,u);
}
low[u] = cnt;
}
set<P>S[maxn];
int main(){
int q;
scanf("%d%d",&n,&q);
for(int i = 1, u,v;i < n;++i){
scanf("%d%d",&u,&v);add(u,v);
}
dfs(1,-1);
for(int i = 1,u,c;i <= q;++i){
int op;scanf("%d",&op);
if(op == 1){
scanf("%d%d",&u,&c);
set<P>::iterator it = S[c].lower_bound({dfn[u],0});
if(it != S[c].end() && (*it).sec <= dfn[u]) continue;
while(it != S[c].end() && (*it).fir <= low[u]){
modify((*it).sec, (*it).fir, -1);
S[c].erase(it++);
}
modify(dfn[u], low[u], 1);
S[c].insert({low[u], dfn[u]});
} else{
scanf("%d",&u);printf("%lld\n", query(dfn[u],low[u]));
}
}
return 0;
}