Put the code first, and update it later.
============================= 2018.3.21UPD ===================== =========
The topic is here
practice
First of all, you need to understand the operation process of the zkw line segment tree. (If you don’t understand Baidu, look at it)
Probably starting from two leaf nodes, maintaining two pointers, one pointing to
One to the left, one to point
The one on the right keeps jumping up. Then imitate this process and also operate on this generalized line segment tree, draw a picture to find out, suppose
the leaf node
,
the leaf node
, a line segment
will be divided into several small line segments that are exactly
the right brothers of all left sons on the chain, and
The left brother of all right sons on the chain.
Be sure to draw! ! ! Watch more! ! !
It's easy once you find this out. press a chain
Divide it into two halves, then vigorously classify and discuss, multiply on the tree, and there are too many details. for example,
and
cases require special handling, and
When the location is more special, it also needs to be judged.
It is recommended to push and watch qwq by yourself. (I was thinking of qwq by myself at the time, and I felt that I came up with a zjoi question and I was cute! Cute! Da!
code
/*
* zkw线段树的科技;
* 一堆细节;
* 考试一定要对拍!不对拍会死的!
*/
#include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x); i<=(y); i++)
#define per(i,x,y) for (int i=(x); i>=(y); i--)
#define N 400010
#define ll long long
using namespace std;
ll read(){
char ch=getchar(); ll x=0; int op=1;
for (; !isdigit(ch); ch=getchar()) if (ch=='-') op=-1;
for (; isdigit(ch); ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return x*op;
}
int n,m,tot,rt,now,clk,a[N],f[N][20],pos[N],in[N],out[N];
ll g[N],h[N],f1s[N],f2s[N],gs[N],hs[N],ans,dep[N];
struct seg{
int l,r,ls,rs,mid;
seg(){ l=r=ls=rs=mid=0; }
}tr[N];
void build(int &o,int l,int r,int d,int fa,bool fl){
o=++tot; in[o]=++clk; tr[o].l=l; tr[o].r=r; dep[o]=d; f[o][0]=fa;
if (!fl){//左儿子
g[o]=g[fa]+d; gs[o]=gs[fa]+1;
h[o]=h[fa]; hs[o]=hs[fa];
f1s[o]=f1s[fa]+d-1; f2s[o]=f2s[fa];
} else{
g[o]=g[fa]; gs[o]=gs[fa];
h[o]=h[fa]+d; hs[o]=hs[fa]+1;
f1s[o]=f1s[fa]; f2s[o]=f2s[fa]+d-1;
}
if (l==r){ pos[l]=o; out[o]=++clk; return; } int k=a[now]; tr[o].mid=k;
if (l<k) now++; build(tr[o].ls,l,k,d+1,o,0);
if (k+1<r) now++; build(tr[o].rs,k+1,r,d+1,o,1);
out[o]=++clk;
}
void print_tree(int u){
printf("id: %d, l=%d, r=%d\n",u,tr[u].l,tr[u].r);
if (tr[u].ls) print_tree(tr[u].ls);
if (tr[u].rs) print_tree(tr[u].rs);
}
int lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
int tmp=dep[x]-dep[y];
per (i,18,0) if (tmp>>i&1) x=f[x][i];
if (x==y) return x;
per (i,18,0) if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
bool isanc(int x,int y){ return in[x]<=in[y] && out[x]>=out[y]; }
int main(){
/*freopen("B.in","r",stdin);
freopen("B.out","w",stdout);*/
n=read();
rep (i,1,n-1) a[i]=read();
m=read();
now=1; build(rt,1,n,0,0,1);
rep (j,1,18) rep (i,1,tot) f[i][j]=f[f[i][j-1]][j-1];
while (m--){
int u=read(),l=read(),r=read(),x,y,z,w,v,tmp;
ans=0;
if (l==1 && r==n){ printf("%d\n",dep[u]); continue; }
x=pos[l-1]; y=pos[r+1]; tmp=lca(x,y); z=tr[tmp].ls; if (l==1 || r==1) z=1;
if (l!=1){
w=lca(x,u);
if (isanc(w,z)){
ll sum=gs[x]-gs[z];
ans+=g[x]-g[z]+sum*dep[u]-2ll*sum*dep[w];
if (w==z && isanc(tr[w].rs,u)) ans-=2;
} else{
ll sum=gs[x]-gs[w];
ans+=g[x]-g[w]+sum*dep[u]-2ll*sum*dep[w];
sum=gs[w]-gs[z];
ans+=g[w]-g[z]+sum*dep[u]-2ll*(f1s[w]-f1s[z]);
if (isanc(tr[w].rs,u)) ans-=2;
}
}
z=tr[tmp].rs; if (l==1 || r==1) z=1;
if (r!=n){
w=lca(y,u);
if (isanc(w,z)){
ll sum=hs[y]-hs[z];
ans+=h[y]-h[z]+sum*dep[u]-2ll*sum*dep[w];
if (w==z && isanc(tr[w].ls,u)) ans-=2;
} else{
ll sum=hs[y]-hs[w];
ans+=h[y]-h[w]+sum*dep[u]-2ll*sum*dep[w];
sum=hs[w]-hs[z];
ans+=h[w]-h[z]+sum*dep[u]-2ll*(f2s[w]-f2s[z]);
if (isanc(tr[w].ls,u)) ans-=2;
}
}
printf("%lld\n",ans);
}
return 0;
}