[bzoj3626]LCA
询问可以理解为将所有l~r的节点到根的路径都打上+1标记,然后询问相当于查询z到根的路径中有多少+1标记,这个问题可以转化为前缀和离线处理,用树链剖分套线段树维护。
还有一种分块的做法,对于每一个节点预处理出其到每一个块的答案,对于每一个块,可以发现f[k]=f[fa]+sz[k],其中sz[k]表示k的子树在这个块内的节点数量,先预处理s在计算f即可,最后块内直接计算,块外暴力(不需要套数据结构,但常数较大,可能过不了)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 50005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 struct ji{ 8 int id,x,y,z; 9 bool operator < (const ji &a)const{ 10 return x<a.x; 11 } 12 }q[N<<1]; 13 struct ji2{ 14 int nex,to; 15 }edge[N<<1]; 16 int E,n,m,x,y,z,k,sz[N],fa[N],top[N],id[N],ans[N],ma[N],head[N],laz[N<<2],f[N<<2]; 17 void add(int x,int y){ 18 edge[E].nex=head[x]; 19 edge[E].to=y; 20 head[x]=E++; 21 } 22 void dfs(int k){ 23 sz[k]=1; 24 for(int i=head[k];i!=-1;i=edge[i].nex){ 25 dfs(edge[i].to); 26 sz[k]+=sz[edge[i].to]; 27 if (sz[edge[i].to]>sz[ma[k]])ma[k]=edge[i].to; 28 } 29 } 30 void dfs2(int k,int t){ 31 id[k]=++x; 32 top[k]=t; 33 if (ma[k])dfs2(ma[k],t); 34 for(int i=head[k];i!=-1;i=edge[i].nex) 35 if (edge[i].to!=ma[k])dfs2(edge[i].to,edge[i].to); 36 } 37 void up(int k,int p,int l,int r){ 38 laz[k]+=p; 39 f[k]+=p*(r-l+1); 40 } 41 void down(int k,int l,int r){ 42 up(L,laz[k],l,mid); 43 up(R,laz[k],mid+1,r); 44 laz[k]=0; 45 } 46 void update(int k,int l,int r,int x,int y){ 47 if ((l>y)||(x>r))return; 48 if ((x<=l)&&(r<=y)){ 49 up(k,1,l,r); 50 return; 51 } 52 update(L,l,mid,x,y); 53 update(R,mid+1,r,x,y); 54 f[k]=f[L]+f[R]+laz[k]*(r-l+1); 55 } 56 int query(int k,int l,int r,int x,int y){ 57 if ((l>y)||(x>r))return 0; 58 if ((x<=l)&&(r<=y))return f[k]; 59 down(k,l,r); 60 return query(L,l,mid,x,y)+query(R,mid+1,r,x,y); 61 } 62 int calc(int k){ 63 int s=0; 64 for(;k;k=fa[top[k]])s+=query(1,1,n,id[top[k]],id[k]); 65 return s; 66 } 67 int main(){ 68 scanf("%d%d",&n,&m); 69 memset(head,-1,sizeof(head)); 70 for(int i=2;i<=n;i++){ 71 scanf("%d",&x); 72 add(++x,i); 73 fa[i]=x; 74 } 75 dfs(1); 76 x=0; 77 dfs2(1,1); 78 for(int i=1;i<=m;i++){ 79 scanf("%d%d%d",&x,&y,&z); 80 if (x)q[++k]=ji{i,x,z+1,-1}; 81 q[++k]=ji{i,y+1,z+1,1}; 82 } 83 sort(q+1,q+k+1); 84 for(int i=1,j=1;i<=n;i++){ 85 for(int k=i;k;k=fa[top[k]])update(1,1,n,id[top[k]],id[k]); 86 for(;q[j].x==i;j++)ans[q[j].id]+=calc(q[j].y)*q[j].z; 87 } 88 for(int i=1;i<=m;i++)printf("%d\n",ans[i]%201314); 89 }