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

2
1 2
10 20
1
0 1 5

Sample Output

2

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 }
View Code

 

 

posted @ 2019-04-12 10:11  zjxxcn  阅读(97)  评论(0编辑  收藏  举报