Given a tree, there are n questions asking about the sum of the depth of the nearest common ancestor of each node I and z within the [l,r] interval.
Thinking: No, then read the solution, and then found that their IQ is seriously inadequate.
See the data range to know must be offline processing, on this offline processing I guess with my IQ does not look at the puzzle is definitely not out of the.
Considering this kind of violence, we mark all the points on Z to the root, and for the points between L and R, search up to the first labeled point to find out its depth statistic answer. It is observed that the depth is actually a few marked points (including itself) above. So, we may as well put Z to the root of the path on the point all +1, for the points between L and R to ask them to the root path on the point of the right and. Careful observation of the above violence is not difficult to find, in fact, the operation is additive, and reversible. That is to say, we can point to the L to R, point I to the root of the path on all +1, instead of asking Z to the root of the path of the point (including itself) the weights and is the answer to this query. Put the query differential, that is, with [1, R]? [1, l? 1] To calculate the answer, now we have a clear solution. from 0 to n? 1 Insert point I in turn, and the point on the path from I to the root is all +1. Ask for answers offline. We now need a data structure to maintain the sum of paths and paths, and obviously the tree-chain or LCT can accomplish this task. The complexity of the tree chain is O ((n + q) log n log n), and the complexity of the LCT is O ((n + q) log n), which can accomplish the task. So far, the topic has been solved by us perfectly.
God problem ...
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 100010 #define INF 0x3f3f3f3f#define Left (POS << 1) #define RIGHT (POS << 1|1) #define CNT (r-l + 1) #define MO 20131 4using namespace Std;struct _ask{bool is_l;int x,z;int id;_ask (bool _,int __,int ___,int ___): is_l (_), X (__), Z (___), ID (_ ___) {}_ask () {}bool operator < (const _ask &a) Const {if (x = = a.x) return Is_l;return x < a.x;}} Ask[max];struct Segtree{long long sum;int c;} Tree[max << 2];int points,asks;int head[max],total;int next[max],aim[max];int Deep[max],father[max],son[max], Size[max];int Pos[max],top[max],cnt;long long ans[max];inline void Add (int x,int y) {next[++total] = head[x];aim[total] = Y;HEAD[X] = total;} void Predfs (int x) {deep[x] = Deep[father[x]] + 1;size[x] = 1;int max_size = 0,p = 0;for (int i = head[x]; i; i = Next[i]) { Predfs (Aim[i]); Size[x] + size[aim[i]];if (Max_size < size[aim[i]]) max_size = Size[aim[i]],p = Aim[i];} SON[X] = p;}void dfs (int x,int _top) {pos[x] = ++cnt;top[x] = _top;if (son[x]) DFS (son[x],_top); for (int i = head[x]; i; i = Next[i]) {if (Aim[i] = = Son[x]) Continue;dfs (Aim[i],aim[i]);}} inline void pushdown (int pos,int cnt) {if (tree[pos].c) {tree[left].sum + = TREE[POS].C * (CNT-(CNT >> 1)); tree[right ].sum + = tree[pos].c * (CNT >> 1), tree[left].c + = tree[pos].c;tree[right].c + tree[pos].c;tree[pos].c = 0;}} void Modify (int l,int r,int x,int y,int pos) {if (L = = x && r = = y) {tree[pos].sum + = Cnt;++tree[pos].c;return;} Pushdown (pos,cnt); int mid = (L + R) >> 1;if (y <= mid) Modify (l,mid,x,y,left); else if (x > Mid) Modify (Mid + 1,r,x , y,right); else {Modify (l,mid,x,mid,left); Modify (mid + 1,r,mid + 1,y,right);} Tree[pos].sum = Tree[left].sum + tree[right].sum;} inline void Modify (int x) {while (x) {Modify (1,cnt,pos[top[x]],pos[x],1); x = Father[top[x]];}} Long long Ask (int l,int r,int x,int y,int pos) {if (L = = = x && y = = r) return tree[pos].sum; Pushdown (pos,cnt); int mid = (L + r) >> 1;if (y <= mid) return Ask (L,mid,x,y,left), if (X > Mid) return ask (mid + 1,r,x,y,right), long long left = Ask (l,mi D,x,mid,left); long Long right = Ask (mid + 1,r,mid + 1,y,right); Inline long long Ask (int x) {Long Long re = 0;while (x) {re + = Ask (1,cnt,pos[top[x]],pos[x],1); x = Father[top[x]];} return re;} int main () {cin >> points >> asks;for (int x,i = 2; I <= points; ++i) {scanf ("%d", &x), ++x; ADD (x,i); father[i] = x;} Predfs (1);D FS, for (int num = 0,x,y,z,i = 1; I <= asks; ++i) {scanf ("%d%d%d", &x,&y,&z); ++x,++y,++z;ask [++num] = _ask (true,x-1,z,i); Ask[++num] = _ask (false,y,z,i);} Sort (ask + 1,ask + (asks << 1) + 1); int j = 1;for (int i = 0; I <= points; ++i) {Modify (i); for (; ask[j].x = i; + +) j) if (ask[j].is_l) ans[ask[j].id] = Ask (ASK[J].Z); elseans[ask[j].id] = (Ask (ASK[J].Z)-ans[ask[j].id])% MO;} for (int i = 1; I <= asks; ++i) printf ("%d\n", (int) ans[i]); return 0;}
Bzoj 3626 Lnoi LCA tree chain split