标签:style color io ar for sp on log ad
题目大意:
维护一棵初始有n个节点的有根树(根节点为1),树上节点编号为1-n,每个点有一个权值wi。
最开始时lastans=0。
思路:开始看到询问是与子树有关的,又要支持动态加点,想到动态维护dfs序,然而一个区间第k大就让splay滚粗了。
然后离线构树也不行。
那么觉得不可做,想到分块乱搞。
然而这是一棵树,如何进行树上分块呢?
我们用一次dfs过程将树分块。
首先,定义根节点在块1中,块1的size为1.
从根节点向下dfs,对于当前点x,依次遍历其儿子,若遍历到儿子son时x所在的块的size小于Maxsize,则将son加入x所在的块,x所在的块的size+1.
否则,建立一个新块,使son加入这个新块,新块的size+1.
每遍历到一个儿子就向下dfs.
然后我们记录两个图,一个是原来的树,一个是块与块之间形成的图,只需要在每次产生新块的时候加一条边即可。
不难发现,块与块之间事实上形成的也是树形结构。
我们再对于每一个块记录下块内所有的权值,并排序。
对于询问,我们从当前节点向下dfs,若遇到一个儿子不属于其所在的块,则转到块与块之间形成的树向下搜索,每遇到一个块就在块里二分找答案。如果儿子依旧属于这个块,那就直接看一下他和x的大小关系即可。若令Maxsize=sqrt(n),这样的复杂度是O(sqrt(n)log(sqrt(n))).
对于加入新点,我们直接在其父亲所在的块中加入一个点即可,需要暴力修改权值的有序序列,复杂度O(sqrt(n)).当然如果父亲所在的块size达到了MAxsize,就新建一个一个点的新块。
如果修改权值,就直接在这个点所在的块的权值序列中暴力删除,插入即可,时间复杂度O(sqrt(n)).
事实上可能取Maxsize=sqrt(n)logn快一些?不过我T了。。。
Code:
#include <cmath> #include <cctype> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; inline int getc() { static const int L = 1 << 15; static char buf[L], *S = buf, *T = buf; if (S == T) { T = (S = buf) + fread(buf, 1, L, stdin); if (S == T) return EOF; } return *S++; } inline int getint() { int c; while(!isdigit(c = getc())); int tmp = c - '0'; while(isdigit(c = getc())) tmp = (tmp << 1) + (tmp << 3) + c - '0'; return tmp; } #define N 30010 #define M 30010 #define Num 5010 #define Size 5010 struct Graph { int head[N + M], next[(N + M)<<1], end[(N + M)<<1], ind; void reset() { ind = 0; memset(head, -1, sizeof(head)); } void addedge(int a, int b) { int q = ind++; end[q] = b; next[q] = head[a]; head[a] = q; } void make(int a, int b) { addedge(a, b); addedge(b, a); } }G; struct Lump { int head[Num], next[Num << 1], end[Num << 1], ind; void reset() { ind = 0; memset(head, -1, sizeof(head)); } void addedge(int a, int b) { int q = ind++; end[q] = b; next[q] = head[a]; head[a] = q; } void make(int a, int b) { addedge(a, b); addedge(b, a); } }Lumps; int w[N + M]; int per, size[Num], sav[Num][Size], belong[N + M], cnt, pa[N + M]; void dfs(int x, int fa) { for(int j = G.head[x]; j != -1; j = G.next[j]) { if (G.end[j] == fa) continue; pa[G.end[j]] = x; if (size[belong[x]] == per) { belong[G.end[j]] = ++cnt, sav[cnt][++size[cnt]] = w[G.end[j]]; Lumps.make(cnt, belong[x]); } else belong[G.end[j]] = belong[x], sav[belong[x]][++size[belong[x]]] = w[G.end[j]]; dfs(G.end[j], x); } } inline int ask_Big(int ins, int x) { sav[ins][size[ins] + 1] = 1 << 30; int L = 1, R = size[ins] + 1, mid; while(L < R) { mid = (L + R) >> 1; if (sav[ins][mid] > x) R = mid; else L = mid + 1; } return size[ins] + 1 - L; } inline int ask_Lump(int x, int fa, int val) { int res = ask_Big(x, val); for(int j = Lumps.head[x]; j != -1; j = Lumps.next[j]) { if (Lumps.end[j] != fa) res += ask_Lump(Lumps.end[j], x, val); } return res; } inline int ask(int x, int fa, int val) { int res = w[x] > val ? 1 : 0; for(int j = G.head[x]; j != -1; j = G.next[j]) { if (G.end[j] != fa) { if (belong[G.end[j]] != belong[x]) res += ask_Lump(belong[G.end[j]], belong[x], val); else res += ask(G.end[j], x, val); } } return res; } void remove(int ins, int val) { int i, j; for(i = 1; i <= size[ins]; ++i) if (sav[ins][i] == val) break; --size[ins]; for(j = i; j <= size[ins]; ++j) sav[ins][j] = sav[ins][j + 1]; } void insert(int ins, int val) { int i, j; for(i = 1; i <= size[ins]; ++i) if (sav[ins][i] > val) break; ++size[ins]; for(j = size[ins]; j > i; --j) sav[ins][j] = sav[ins][j - 1]; sav[ins][i] = val; } int main() { int n = getint(); register int i; int a, b; G.reset(); for(i = 1; i < n; ++i) { a = getint(), b = getint(); G.make(a, b); } for(i = 1; i <= n; ++i) w[i] = getint(); per = (int)sqrt(n * log(n)/log(2)); Lumps.reset(); belong[1] = size[++cnt] = 1, sav[cnt][1] = w[1]; dfs(1, -1); for(i = 1; i <= cnt; ++i) sort(sav[i] + 1, sav[i] + size[i] + 1); int Q, ope, lastans = 0; Q = getint(); while(Q--) { ope = getint(), a = getint(), b = getint(); a ^= lastans; b ^= lastans; if (!ope) printf("%d\n", lastans = ask(a, pa[a], b)); else if (ope == 1) { remove(belong[a], w[a]); insert(belong[a], w[a] = b); } else { w[++n] = b; pa[n] = a; if (size[belong[a]] == per) { belong[n] = ++cnt; size[cnt] = 1; sav[cnt][1] = w[n]; G.make(a, n); Lumps.make(belong[a], cnt); } else { belong[n] = belong[a]; insert(belong[a], w[n]); G.make(a, n); } } } return 0; }
标签:style color io ar for sp on log ad
原文地址:http://blog.csdn.net/wyfcyx_forever/article/details/40180723