bzoj 3720 Gty的妹子树
Description
我曾在弦歌之中听过你,
檀板声碎,半出折子戏。
舞榭歌台被风吹去,
岁月深处尚有余音一缕……
Gty神(xian)犇(chong)从来不缺妹子……
他来到了一棵妹子树下,发现每个妹子有一个美丽度……
由于Gty很哲♂学,他只对美丽度大于某个值的妹子感兴趣。
他想知道某个子树中美丽度大于k的妹子个数。
某个妹子的美丽度可能发生变化……
树上可能会出现一只新的妹子……
维护一棵初始有n个节点的有根树(根节点为1),树上节点编号为1-n,每个点有一个权值wi。
支持以下操作:
0 u x 询问以u为根的子树中,严格大于x的值的个数。(u^=lastans,x^=lastans)
1 u x 把u节点的权值改成x。(u^=lastans,x^=lastans)
2 u x 添加一个编号为"当前树中节点数+1"的节点,其父节点为u,其权值为x。(u^=lastans,x^=lastans)
最开始时lastans=0。
Input
输入第一行包括一个正整数n(1<=n<=30000),代表树上的初始节点数。
接下来n-1行,每行2个整数u,v,为树上的一条无向边。
任何时刻,树上的任何权值大于等于0,且两两不同。
接下来1行,包括n个整数wi,表示初始时每个节点的权值。
接下来1行,包括1个整数m(1<=m<=30000),表示操作总数。
接下来m行,每行包括三个整数 op,u,v:
op,u,v的含义见题目描述。
保证题目涉及的所有数在int内。
Output
对每个op=0,输出一行,包括一个整数,意义见题目描述。
Sample Input
1 2
10 20
1
0 1 5
Sample Output
HINT
2017.9.28新加数据一组by GXZlegend,未重测
思路: 吐槽一下题目的数据范围有误,n好像要比30000大。
这题可以按照size的大小分块,如果父亲所在的块的点的数量小于sz,那么就把当前节点加到父亲所在的块里面。
这样分块的方法可以保证块的大小和直径,但是不能保证块的数量。(感觉要被卡,逃 。。。)
块里面用普通的一维数组记录每个不同的权值,插入和修改的时候用暴力的插入排序维护。
时间复杂度$O(n*\sqrt{n}*\log n)$,时间复杂度比较高,但是可以卡过。
本题最好的方法是用替罪羊树套treap来写。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define rep(i,a,b) for(int i=a;i<=b;i++) 4 #define Rep(i,a,b) for(int i=a;i>=b;i--) 5 #define ms(i,a) memset(a,i,sizeof(a)) 6 int const N = 100000 + 3; 7 template<class T>void read(T &x) { 8 x = 0; 9 char c = 0; 10 while(!isdigit((c))) c = getchar(); 11 while(isdigit(c)) x = x * 10 + (c ^ 48), c = getchar(); 12 } 13 struct edge { 14 int to, nt; 15 } e[N << 2]; 16 struct block { 17 int a[300], num; 18 void ins(int x) { 19 num++; 20 int j = num - 1; 21 while(j && a[j] > x) a[j + 1] = a[j], j--; 22 a[j + 1] = x; 23 } 24 void modify(int x, int y) { 25 int t = lower_bound(a + 1, a + num + 1, x) - a; 26 rep(i, t + 1, num) a[i - 1] = a[i]; 27 num--; 28 ins(y); 29 } 30 int query(int x) { 31 return num - (upper_bound(a + 1, a + num + 1, x) - a) + 1; 32 } 33 } b[10000]; 34 int h[N], cnt, H[N], bl[N], n, m, a[N], sz, sum, ans,f[N]; 35 void add(int a, int b) { 36 e[++cnt].to = b; 37 e[cnt].nt = h[a]; 38 h[a] = cnt; 39 } 40 void Add(int a, int b) { 41 e[++cnt].to = b; 42 e[cnt].nt = H[a]; 43 H[a] = cnt; 44 } 45 void dfs(int x) { 46 if(b[bl[f[x]]].num >= sz) { 47 bl[x] = ++sum; 48 b[sum].ins(a[x]); 49 Add(bl[f[x]], sum); 50 } else { 51 bl[x] = sum; 52 b[sum].ins(a[x]); 53 } 54 for(int i = h[x]; i; i = e[i].nt) { 55 int v = e[i].to; 56 if(v == f[x]) continue; 57 f[v]=x; 58 dfs(v); 59 } 60 } 61 void getblock(int x, int y) { 62 ans += b[x].query(y); 63 for(int i = H[x]; i; i = e[i].nt) { 64 int v = e[i].to; 65 getblock(v, y); 66 } 67 } 68 void getans(int x, int y) { 69 if(a[x] > y) ans++; 70 for(int i = h[x]; i; i = e[i].nt) { 71 int v = e[i].to; 72 if(v == f[x]) continue; 73 if(bl[v] == bl[x]) getans(v, y); 74 else getblock(bl[v], y); 75 } 76 } 77 int main() { 78 read(n); 79 sz = sqrt(n); 80 rep(i, 1, n - 1) { 81 int x, y; 82 read(x); 83 read(y); 84 add(x, y); 85 add(y, x); 86 } 87 rep(i, 1, n) read(a[i]); 88 dfs(1); 89 read(m); 90 while(m--) { 91 int k, x, y; 92 read(k); 93 read(x); 94 read(y); 95 x ^= ans; 96 y ^= ans; 97 if(k == 0) { 98 ans = 0; 99 getans(x,y); 100 printf("%d\n", ans); 101 } 102 if(k == 1) { 103 b[bl[x]].modify(a[x], y); 104 a[x] = y; 105 } 106 if(k == 2) { 107 a[++n] = y; 108 f[n]=x; 109 add(x, n); 110 if(b[bl[x]].num >= sz) { 111 bl[n] = ++sum; 112 b[sum].ins(y); 113 Add(bl[x], sum); 114 } else { 115 bl[n] = bl[x]; 116 b[bl[n]].ins(y); 117 } 118 } 119 } 120 return 0; 121 }