方案一:[a,b] 的lca和可以变成[1,a] 与 [1,b] 的答案和。
于是离线。
copied from wlc1121
方案二:
询问的是区间,于是想到莫队
树剖+线段树同上维护。
我自己没写过一个根号*两个log==QAQ留给底层优化大师去实现吧...
---------分割线---------
(隔壁q234rty说可以用欧拉序列去掉一个log)
(隔壁q234rty还说bzoj跑得快的应该是这样写的)
TMD被卡取膜卡了两天才卡出来
(还要感谢隔壁q234rty帮忙向bzoj要数据)
毕竟是氪金dalao~
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;++j)
#define red(j,k,l) for (int j=k;j>=l;--j)
#define N 100005
using namespace std;
struct Qry{
int k,x,i,ans;
} Q[N*2];
int n,T,cnt,to[N],ne[N],st[N],deep[N],fa[N],sz[N],son[N];
int top[N],id[N],dfn[N],tr[4*N],fg[4*N];
void add(int k,int l){
to[++cnt]=l;
ne[cnt]=st[k];
st[k]=cnt;
}
void dfs1(int k,int ff){
fa[k]=ff;deep[k]=deep[ff]+1;
sz[k]=1;
son[k]=0;
for (int i=st[k];i;i=ne[i]){
dfs1(to[i],k);
sz[k]+=sz[to[i]];
if (sz[to[i]]>sz[son[k]]) son[k]=to[i];
}
}
void dfs2(int k,bool wlc1121){
if (wlc1121) top[k]=top[fa[k]];
else top[k]=k;
id[k]=++cnt;
dfn[cnt]=k;
if (son[k]>0) dfs2(son[k],1);
for (int i=st[k];i;i=ne[i])
if (to[i]!=son[k]) dfs2(to[i],0);
}
bool cmp(const Qry &x,const Qry &y){
return x.k<y.k;
}
bool Cmp(const Qry &x,const Qry &y){
return x.i<y.i;
}
void Up(int k,int l,int r,int o,int p){
if (l>p||r<o) return;
if (l>=o&&r<=p){
tr[k]+=r-l+1;
fg[k]++;
return;
}
if (fg[k]){
tr[2*k]+=fg[k]*((l+r)/2-l+1);
tr[2*k+1]+=fg[k]*(r-(l+r)/2);
fg[2*k]+=fg[k];
fg[2*k+1]+=fg[k];
fg[k]=0;
}
Up(2*k,l,(l+r)/2,o,p);
Up(2*k+1,(l+r)/2+1,r,o,p);
tr[k]=tr[2*k]+tr[2*k+1];
}
void up(int x,int y){
for (;top[x]!=top[y];x=fa[top[x]]){
if (deep[top[x]]<deep[top[y]]) swap(x,y);
Up(1,1,n,id[top[x]],id[x]);
}
if (deep[x]>deep[y]) swap(x,y);
Up(1,1,n,id[x],id[y]);
}
int ask(int k,int l,int r,int o,int p){
if (l>p||r<o) return 0;
if (l>=o&&r<=p) return tr[k];
if (fg[k]){
tr[2*k]+=fg[k]*((l+r)/2-l+1);
tr[2*k+1]+=fg[k]*(r-(l+r)/2);
fg[2*k]+=fg[k];
fg[2*k+1]+=fg[k];
fg[k]=0;
}
return ask(2*k,l,(l+r)/2,o,p)+ask(2*k+1,(l+r)/2+1,r,o,p);
}
int qry(int x,int y){
int ans=0;
for (;top[x]!=top[y];x=fa[top[x]]){
if (deep[top[x]]<deep[top[y]]) swap(x,y);
ans=(ans+ask(1,1,n,id[top[x]],id[x]))%201314;
}
if (deep[x]>deep[y]) swap(x,y);
ans=(ans+ask(1,1,n,id[x],id[y]))%201314;
return ans;
}
int main(){
scanf("%d%d",&n,&T);
rep(i,2,n){
int k;
scanf("%d",&k);
k++;
add(k,i);
}
rep(i,1,T){
int k,l,poi;
scanf("%d%d%d",&k,&l,&poi);
k++,l++,poi++;
Q[2*i-1].k=k-1,Q[2*i].k=l;
Q[2*i-1].x=Q[2*i].x=poi;
Q[2*i-1].i=2*i;Q[2*i].i=i*2-1;
}
dfs1(1,1);cnt=0;
dfs2(1,0);
sort(Q+1,Q+T*2+1,cmp);
int nw=1;
while (nw<=2*T&&Q[nw].k==0) Q[nw].ans=0,nw++;
rep(i,1,n){
up(1,i);
while (nw<=2*T&&Q[nw].k==i)
Q[nw].ans=(qry(1,Q[nw].x))%201314,nw++;
}
sort(Q+1,Q+2*T+1,Cmp);
rep(i,1,T) printf("%d\n",(Q[2*i-1].ans%201314-Q[2*i].ans%201314+201314)%201314);
}