[LNOI2014]LCA
Description
给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)
Input
第一行2个整数n q。
接下来n-1行,分别表示点1到点n-1的父节点编号。
接下来q行,每行3个整数l r z。
Output
输出q行,每行表示一个询问的答案。每个答案对201314取模输出
Sample Input
5 2
0
0
1
1
1 4 3
1 4 2
0
0
1
1
1 4 3
1 4 2
Sample Output
8
5
5
HINT
共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。
http://www.cnblogs.com/Y-E-T-I/p/8182129.html
根这道题很像
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 struct Node 8 { 9 int next,to; 10 }edge[100001]; 11 int num,head[50001],size[50001],dep[50001],son[50001],top[50001],cnt,dfn[50001],pos; 12 int ch[150*50001][2],root[50001],sum[150*50001],lazy[150*50001],n,fa[50001],pre[50001],ans; 13 void add(int u,int v) 14 { 15 num++; 16 edge[num].next=head[u]; 17 head[u]=num; 18 edge[num].to=v; 19 } 20 void dfs1(int x,int pa) 21 {int i; 22 size[x]=1; 23 for (i=head[x];i;i=edge[i].next) 24 { 25 int v=edge[i].to; 26 if (v!=pa) 27 { 28 fa[v]=x; 29 dep[v]=dep[x]+1; 30 dfs1(v,x); 31 size[x]+=size[v]; 32 if (size[son[x]]<size[v]) son[x]=v; 33 } 34 } 35 } 36 void dfs2(int x,int pa,int tp) 37 {int i; 38 top[x]=tp; 39 dfn[x]=++cnt; 40 if (son[x]) dfs2(son[x],x,tp); 41 for (i=head[x];i;i=edge[i].next) 42 { 43 int v=edge[i].to; 44 if (v!=pa&&v!=son[x]) 45 { 46 dfs2(v,x,v); 47 } 48 } 49 } 50 void update(int &rt,int l,int r,int L,int R,int last) 51 { 52 if (rt<=last) 53 { 54 int Rt=rt; 55 rt=++pos; 56 ch[rt][0]=ch[Rt][0];ch[rt][1]=ch[Rt][1]; 57 sum[rt]=sum[Rt]; 58 lazy[rt]=lazy[Rt]; 59 } 60 if (l>=L&&r<=R) 61 { 62 sum[rt]+=(r-l+1); 63 sum[rt]%=201314; 64 lazy[rt]+=1; 65 return; 66 } 67 int mid=(l+r)/2; 68 if (L<=mid) update(ch[rt][0],l,mid,L,R,last); 69 if (R>mid) update(ch[rt][1],mid+1,r,L,R,last); 70 sum[rt]=(sum[ch[rt][0]]+sum[ch[rt][1]]+(r-l+1)*lazy[rt])%201314; 71 } 72 int query(int rt,int l,int r,int L,int R) 73 { 74 if (!rt) return 0; 75 if (l>=L&&r<=R) 76 { 77 return sum[rt]; 78 } 79 int mid=(l+r)/2,s=0; 80 if (L<=mid) s+=query(ch[rt][0],l,mid,L,R); 81 if (R>mid) s+=query(ch[rt][1],mid+1,r,L,R); 82 s%=201314; 83 return s+(min(r,R)-max(l,L)+1)*lazy[rt]; 84 } 85 void change(int &rt,int x,int last) 86 { 87 while (top[x]) 88 { 89 update(rt,1,n,dfn[top[x]],dfn[x],last); 90 x=fa[top[x]]; 91 } 92 } 93 int ask(int r,int x) 94 { 95 int s=0; 96 while (top[x]) 97 { 98 s+=query(root[r],1,n,dfn[top[x]],dfn[x]); 99 s%=201314; 100 x=fa[top[x]]; 101 } 102 return s; 103 } 104 int main() 105 {int q,i,v,l,r,z; 106 cin>>n>>q; 107 for (i=2;i<=n;i++) 108 { 109 scanf("%d",&v);v++; 110 add(v,i); 111 } 112 dep[1]=1; 113 dfs1(1,0); 114 dfs2(1,0,1); 115 for (i=1;i<=n;i++) 116 { 117 root[i]=root[i-1]; 118 change(root[i],i,pre[i-1]); 119 pre[i]=pos; 120 } 121 for (i=1;i<=q;i++) 122 { 123 scanf("%d%d%d",&l,&r,&z); 124 l++;r++;z++; 125 ans=((ask(r,z)-ask(l-1,z)+201314)%201314)%201314; 126 printf("%d\n",ans); 127 } 128 }