Bzoj3626 [LNOI2014]LCA
Posted SilverNebula
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj3626 [LNOI2014]LCA相关的知识,希望对你有一定的参考价值。
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 2007 Solved: 800
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。
Source
树链剖分+差分
如果只有一个询问区间的话,可以暴力处理[L,R]区间内的每一个点,将结点到根的路径上的每个点权值+1,之后统计z到根结点路径上的点权和,就是答案。
↑可以用树链剖分来维护,做到O(nlog(n))复杂度。
对于多个询问区间,可以O(n)扫描1到n的每个结点,如上添加权值,若某个点是询问区间起点,记录该询问的“初始状态”ans1,若某个点是询问区间终点,记录该询问的“终状态”ans2,ans2-ans1就是该询问的答案。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<vector> 7 #define lc rt<<1 8 #define rc rt<<1|1 9 using namespace std; 10 const int mod=201314; 11 const int mxn=50010; 12 int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 15 while(ch>=‘0‘ && ch<=‘9‘){x=x*10-‘0‘+ch;ch=getchar();} 16 return x*f; 17 } 18 struct edge{int v,nxt;}e[mxn<<1]; 19 int hd[mxn],mct=0; 20 void add_edge(int u,int v){ 21 e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return; 22 } 23 struct node{int fa,son;int top,size;int w,e;}t[mxn]; 24 int dep[mxn],sz=0; 25 void DFS1(int u,int fa){ 26 dep[u]=dep[fa]+1; 27 t[u].fa=fa;t[u].size=1; 28 for(int i=hd[u];i;i=e[i].nxt){ 29 int v=e[i].v; 30 DFS1(v,u); 31 t[u].size+=t[v].size; 32 if(t[v].size>t[t[u].son].size){ 33 t[u].son=v; 34 } 35 } 36 return; 37 } 38 void DFS2(int u,int top){ 39 t[u].w=++sz;t[u].top=top; 40 if(t[u].son){ 41 DFS2(t[u].son,top); 42 for(int i=hd[u];i;i=e[i].nxt){ 43 int v=e[i].v; 44 if(v!=t[u].son && v!=t[u].fa){ 45 DFS2(v,v); 46 } 47 } 48 } 49 t[u].e=sz; 50 return; 51 } 52 struct sgt{int sum,mk;}st[mxn<<2]; 53 void pushup(int rt){st[rt].sum=(st[lc].sum+st[rc].sum)%mod;return;} 54 void pushdown(int l,int r,int rt){ 55 if(st[rt].mk){ 56 st[lc].mk+=st[rt].mk; 57 st[rc].mk+=st[rt].mk; 58 int mid=(l+r)>>1; 59 (st[lc].sum+=st[rt].mk*(mid-l+1))%=mod; 60 (st[rc].sum+=st[rt].mk*(r-mid))%=mod; 61 st[rt].mk=0; 62 } 63 return; 64 } 65 void update(int L,int R,int v,int l,int r,int rt){ 66 if(L<=l && r<=R){ 67 st[rt].mk+=v; 68 (st[rt].sum+=v*(r-l+1))%=mod; 69 return; 70 } 71 if(st[rt].mk)pushdown(l,r,rt); 72 int mid=(l+r)>>1; 73 if(L<=mid)update(L,R,v,l,mid,lc); 74 if(R>mid)update(L,R,v,mid+1,r,rc); 75 pushup(rt); 76 return; 77 } 78 int qsum(int L,int R,int l,int r,int rt){ 79 if(L<=l && r<=R){return st[rt].sum;} 80 if(st[rt].mk)pushdown(l,r,rt); 81 int mid=(l+r)>>1; 82 int res=0; 83 if(L<=mid) res+=qsum(L,R,l,mid,lc); 84 if(R>mid) res+=qsum(L,R,mid+1,r,rc); 85 return res%mod; 86 } 87 void tadd(int x,int y,int v){ 88 while(t[x].top!=t[y].top){ 89 if(dep[t[x].top]<dep[t[y].top])swap(x,y); 90 update(t[t[x].top].w,t[x].w,v,1,sz,1); 91 x=t[t[x].top].fa; 92 } 93 if(dep[x]>dep[y])swap(x,y); 94 update(t[x].w,t[y].w,v,1,sz,1); 95 return; 96 } 97 int asksum(int x,int y){ 98 int res=0; 99 while(t[x].top!=t[y].top){ 100 if(dep[t[x].top]<dep[t[y].top])swap(x,y); 101 (res+=qsum(t[t[x].top].w,t[x].w,1,sz,1))%=mod; 102 x=t[t[x].top].fa; 103 } 104 if(dep[x]>dep[y])swap(x,y); 105 res+=qsum(t[x].w,t[y].w,1,sz,1); 106 return res; 107 } 108 struct query{ 109 int x,v,z;int id; 110 }q[mxn<<1]; 111 int qct=0; 112 int cmp(const query a,const query b){ 113 if(a.x!=b.x)return a.x<b.x; 114 return a.id<b.id; 115 } 116 int ans[mxn]; 117 int n,Q; 118 int main() 119 { 120 n=read();Q=read(); 121 int i,j; 122 for(i=2;i<=n;i++){//点编号整体+1 123 j=read()+1; 124 add_edge(j,i); 125 } 126 DFS1(1,0); 127 DFS2(1,1); 128 int x,y,z; 129 for(i=1;i<=Q;i++){ 130 x=read()+1;y=read()+1;z=read()+1; 131 q[++qct].id=i;q[qct].z=z;q[qct].x=x-1;q[qct].v=1; 132 q[++qct].id=i;q[qct].z=z;q[qct].x=y;q[qct].v=-1; 133 } 134 sort(q+1,q+qct+1,cmp); 135 int hed=1; 136 for(i=1;i<=qct;i++){ 137 while(hed<=q[i].x){ 138 tadd(hed,1,1); 139 hed++; 140 } 141 if(q[i].v==1)ans[q[i].id]-=asksum(q[i].z,1); 142 else ans[q[i].id]+=asksum(q[i].z,1);//差分答案 143 } 144 for(i=1;i<=Q;i++)printf("%d\n",(ans[i]%mod+mod)%mod); 145 return 0; 146 }
以上是关于Bzoj3626 [LNOI2014]LCA的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]