P4211 [LNOI2014]LCA
阿新 • • 發佈:2019-01-27
又一鬼題
對於每次查詢
把l-r到跟的路上+1
然後深度就是這個位置的全職
然後查分一下,查詢r-l
這樣就可以離線記下查詢位置
只新增,不用刪除
就可以利用之前的資訊了
// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#define mid (l+r>>1)
using namespace std;
const int M=2e6+5,p=201314;
int n,m,head[M],tot,cnt,nex[M*2 ],to[M*2],id[M],size[M],top[M],son[M],f[M],c[M],ans[M],root=1;
vector<int> L[M],R[M];
struct SEG{
int sum[M],add[M];SEG(){memset(sum,0,sizeof sum);memset(add,0,sizeof add);}
void update(int o){sum[o]=(sum[o<<1]+sum[o<<1|1])%p;}
void pushdown(int o,int l,int r){
if (add[o]){
add[o<<1]=(add[o]+add[o<<1])%p;add[o<<1|1]=(add[o<<1|1]+add[o])%p;
sum[o<<1]=(sum[o<<1]+add[o]*(mid-l+1)%p)%p;sum[o<<1|1]=(sum[o<<1|1]+add[o]*(r-mid)%p)%p;
add[o]=0;
}
}
void modify(int o,int l,int r,int ql,int qr){
if(l>qr||r<ql) return ;
if(ql<=l&&r<=qr) {sum[o]=(sum[o]+r-l+1)%p,add[o]=(add[o]+1)%p;return;}
pushdown(o,l,r);
modify(o<<1,l,mid,ql,qr);
modify(o<<1|1,mid+1,r,ql,qr);
update(o);
}
int query(int o,int l,int r,int ql,int qr){
if(l>qr||r<ql) return 0;
if(ql<=l&&r<=qr) {return sum[o];}
pushdown(o,l,r);
return query(o<<1,l,mid,ql,qr)+query(o<<1|1,mid+1,r,ql,qr);
}
}T;
void add(int u,int v){
to[++tot]=v;
nex[tot]=head[u];
head[u]=tot;
}
void dfs(int x){ size[x]=1;
for(int i=head[x],tmp;i;i=nex[i]){
dfs(tmp=to[i]);size[x]+=size[tmp];
son[x]=(size[tmp]>size[son[x]])?tmp:son[x];
}
}
void dfs2(int x,int ff){
id[x]=++cnt;top[x]=ff;
if(!son[x]) return ;
dfs2(son[x],ff);
for(int i=head[x],tmp;i;i=nex[i])
if(!id[to[i]])dfs2(to[i],to[i]);
}
void modify(int x){
while(x){
T.modify(1,1,cnt,id[top[x]],id[x]);
x=f[top[x]];
}
}
int query(int x){int ans=0;
while(x){
ans=(ans+T.query(1,1,cnt,id[top[x]],id[x]))%p;
x=f[top[x]];
}return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=2,v;i<=n;i++){
scanf("%d",&v);v++;
add(f[i]=v,i);
}
dfs(root);dfs2(root,root);
for(int i=1,l,r;i<=m;i++) {
scanf("%d%d%d",&l,&r,&c[i]);r++;c[i]++;
L[l].push_back(i);
R[r].push_back(i);
}
for(int i=1;i<=n;i++){
modify(i);
for(int j=0;j<L[i].size();j++) ans[L[i][j]]=(ans[L[i][j]]-query(c[L[i][j]]))%p;
for(int j=0;j<R[i].size();j++) ans[R[i][j]]=(ans[R[i][j]]+query(c[R[i][j]]))%p;
}
for(int i=1;i<=m;i++) printf("%d\n",(ans[i]%p+p)%p);
}