这个题在考场上应该是能搞出来的 可是当时debuff太强 没敢想正解 写完了250行的暴力
正解呢 就是类似zkw线段树 我们从叶节点
l−1
和
r+1
一直走直到碰在一起 这样搞出了一条左链和一条右链 左链上的右兄弟和右链上的左兄弟就是所有要找的点 然后我们讨论下查询点
u
和链底的lca的位置 进而可以知道链上所有点和
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=400005;
int n;
int ls[N],rs[N];
const int K=19;
int depth[N],fat[N][K];
int lcnt[N],rcnt[N]; ll lsum[N],rsum[N];
int idx[N];
int lp[N],rp[N];
inline void dfs(int &u,int fa,int l,int r,bool left){
u=++n; lp[n]=l; rp[n]=r;
fat[u][0]=fa; depth[u]=depth[fa]+1;
for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1];
lcnt[u]=lcnt[fa]+left,lsum[u]=lsum[fa]+left*depth[u];
rcnt[u]=rcnt[fa]+(!left),rsum[u]=rsum[fa]+(!left)*depth[u];
if (l==r) return void(idx[l]=n);
int mid; read(mid);
dfs(ls[u],u,l,mid,1);
dfs(rs[u],u,mid+1,r,0);
}
inline int LCA(int u,int v){
if (depth[u]<depth[v]) swap(u,v);
for (int k=K-1;~k;k--)
if ((depth[u]-depth[v])>>k&1)
u=fat[u][k];
if (u==v) return u;
for (int k=K-1;~k;k--)
if (fat[u][k]!=fat[v][k])
u=fat[u][k],v=fat[v][k];
return fat[u][0];
}
int _n;
ll ans=0;
inline ll Lpath(int a,int b,int u,int p){
ans+=lsum[a]-lsum[b];
ans+=(ll)(lcnt[a]-lcnt[b])*depth[u];
ll ret=0;
int lca=LCA(u,a),t=lca;
if (depth[lca]<depth[b]) t=b; else if (rs[lca] && lp[rs[lca]]>p) ret+=depth[LCA(rs[lca],u)]-depth[lca];
ret+=(ll)(lcnt[a]-lcnt[t])*depth[lca];
ret+=(lsum[t]-lsum[b])-(lcnt[t]-lcnt[b]);
ans-=2*ret;
}
inline ll Rpath(int a,int b,int u,int p){
ans+=rsum[a]-rsum[b];
ans+=(ll)(rcnt[a]-rcnt[b])*depth[u];
ll ret=0;
int lca=LCA(u,a),t=lca;
if (depth[lca]<depth[b]) t=b; else if (ls[lca] && rp[ls[lca]]<p) ret+=depth[LCA(ls[lca],u)]-depth[lca];
ret+=(ll)(rcnt[a]-rcnt[t])*depth[lca];
ret+=(rsum[t]-rsum[b])-(rcnt[t]-rcnt[b]);
ans-=ret*2;
}
int main(){
int Q,rt,u,l,r;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(_n); dfs(rt,0,1,_n,0);
read(Q);
while (Q--){
read(u); read(l); read(r);
if (l==1 && r==_n) { printf("%d\n",depth[u]-1); continue; }
ans=0;
if (l==1){
Rpath(idx[r+1],1,u,r+1);
}else if (r==_n){
Lpath(idx[l-1],1,u,l-1);
}else{
int lca=LCA(idx[l-1],idx[r+1]);
Lpath(idx[l-1],ls[lca],u,l-1);
Rpath(idx[r+1],rs[lca],u,r+1);
}
printf("%lld\n",ans);
}
return 0;
}