1. 程式人生 > >HDU 6394 Tree 分塊

HDU 6394 Tree 分塊

typedef bit for 分塊 else 訪問 bbc print std

Tree

題意: 給你一顆樹, 每一個節點都有一個權值, 如果一個石頭落在某個節點上, 他就會往上跳這個的點的權值步。 現在有2種操作, 1 把一個石頭放在 x 的位置 詢問有跳幾次才跳出這棵樹, 2 修改某個節點的權值。

解法:樹上分塊, 用dfs分好塊之後。 對於每一塊都處理出如果石頭落在某個位置之後他跳出這個塊之後的位置和次數。

每次更新都自己這一塊的所有子節點, 然後找第k個父親的時候用倍增優化。

對於每次詢問都跳到0號點之後,返回所經過的次數。

我們可以對屬於同一塊內的節點重新建立邊, 因為我們在更新的時候不會直接訪問到別的塊的點, 所以重新建立邊,避免遍歷不需要的邊(快了200ms)。

代碼:

技術分享圖片
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
  4 #define LL long long
  5 #define ULL unsigned LL
  6 #define fi first
  7 #define se second
  8 #define pb push_back
  9 #define lson l,m,rt<<1
 10
#define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e5 + 100; 18 int n, m, b; 19 int
head[N], to[N], nt[N]; /// E1 20 int head2[N], to2[N], nt2[N]; /// E2 21 int Stack[N], belong[N]; 22 int jump[N], tto[N], cnt[N]; 23 int tot, top, type, tot2; 24 int anc[N][20]; 25 inline void add2(int u, int v){ 26 to2[tot2] = v; 27 nt2[tot2] = head2[u]; 28 head2[u] = tot2++; 29 } 30 inline void add(int u, int v){ 31 to[tot] = v; 32 nt[tot] = head[u]; 33 head[u] = tot++; 34 } 35 void dfs(int u){ 36 int now = top, v; 37 for(int i = head[u]; ~i; i = nt[i]){ 38 v = to[i]; 39 anc[v][0] = u; 40 for(int i = 1; i < 20; i++) 41 anc[v][i] = anc[anc[v][i-1]][i-1]; 42 dfs(v); 43 if(top-now >= b){ 44 ++type; 45 while(top!=now){ 46 belong[Stack[top--]] = type; 47 } 48 } 49 } 50 Stack[++top] = u; 51 } 52 inline int Find(int x, int k){ 53 for(int i = 19; i >= 0; i--) 54 if((k>>i)&1) x = anc[x][i]; 55 return x; 56 } 57 inline void Update(int x){ 58 int z = jump[x]; 59 if(belong[z] == belong[x]){ 60 tto[x] = tto[z]; 61 cnt[x] = cnt[z] + 1; 62 } 63 else { 64 tto[x] = z; 65 cnt[x] = 1; 66 } 67 } 68 void Build(int x){ 69 Update(x); 70 for(int i = head[x]; ~i; i = nt[i]) 71 Build(to[i]); 72 } 73 inline int solve(int p){ 74 int ret = 0; 75 while(p){ 76 ret += cnt[p]; 77 p = tto[p]; 78 } 79 return ret; 80 } 81 void dUpdate(int x){ 82 Update(x); 83 for(int i = head2[x]; ~i; i = nt2[i]){ 84 dUpdate(to2[i]); 85 } 86 } 87 void dfs2(int x){ 88 for(int i = head[x]; ~i; i = nt[i]){ 89 if(belong[x] == belong[to[i]]){ 90 add2(x, to[i]); 91 } 92 dfs2(to[i]); 93 } 94 } 95 int main(){ 96 int t, x; 97 scanf("%d", &t); 98 while(t--){ 99 scanf("%d", &n); 100 b = sqrt(n); 101 tot = 0;top = 0; type = 0;tot2 = 0; 102 memset(head, -1, sizeof(int)*(n+1)); 103 memset(head2, -1, sizeof(int)*(n+1)); 104 for(int i = 2; i <= n; i++){ 105 scanf("%d", &x); 106 add(x, i); 107 } 108 dfs(1); 109 while(top) belong[Stack[top--]] = type; 110 dfs2(1); 111 for(int i = 1; i <= n; i++){ 112 scanf("%d", &x); 113 jump[i] = Find(i, x); 114 } 115 Build(1); 116 scanf("%d", &m); 117 int op, k; 118 while(m--){ 119 scanf("%d", &op); 120 if(op == 1) { 121 scanf("%d", &x); 122 printf("%d\n", solve(x)); 123 } 124 else { 125 scanf("%d%d", &x, &k); 126 jump[x] = Find(x, k); 127 dUpdate(x); 128 } 129 } 130 } 131 return 0; 132 }
View Code

HDU 6394 Tree 分塊