bzoj 3720 Gty的妹子樹
阿新 • • 發佈:2019-04-12
如果 closed bit b- lse getchar 變化 一行 ons
支持以下操作:
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。
接下來1行,包括n個整數wi,表示初始時每個節點的權值。
接下來1行,包括1個整數m(1<=m<=30000),表示操作總數。
接下來m行,每行包括三個整數 op,u,v:
op,u,v的含義見題目描述。
保證題目涉及的所有數在int內。
1 2
10 20
1
0 1 5
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
21 2
10 20
1
0 1 5
Sample Output
2HINT
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
bzoj 3720 Gty的妹子樹