• LOJ2570 [ZJOI2017]线段树


    传送门

    #include <bits/stdc++.h>
    const int N=800005,W=19;
    typedef long long ll;
    int f[N][W+1],l[N],r[N],sl[N],sr[N],ls[N],rs[N],deep[N],cnt,rt,pos[N],n,Q,u,L,R;
    ll suml[N],sumr[N];
    int build(int fa,int L,int R){
    	int k=++cnt;
    	f[k][0]=fa;
    	l[k]=L,r[k]=R;
    	if (L==R){
    		pos[L]=k;
    		return k;
    	}
    	int mid;
    	scanf("%d",&mid);
    	ls[k]=build(k,L,mid);
    	rs[k]=build(k,mid+1,R);
    	return k;
    }
    int LCA(int x,int y){
    	if (deep[x]<deep[y]) std::swap(x,y);
    	for (int i=W;i>=0;i--)
    		if (deep[f[x][i]]>=deep[y]) x=f[x][i];
    	if (x==y) return x;
    	for (int i=W;i>=0;i--)
    		if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    void dfs(int x){
    	if (ls[x]){
    		int u=ls[x];
    		deep[u]=deep[x]+1;
    		sl[u]=sl[x]+1;
    		suml[u]=suml[x]+deep[u];
    		sr[u]=sr[x];
    		sumr[u]=sumr[x];
    		dfs(u);
    	}
    	if (rs[x]){
    		int u=rs[x];
    		deep[u]=deep[x]+1;
    		sl[u]=sl[x];
    		suml[u]=suml[x];
    		sr[u]=sr[x]+1;
    		sumr[u]=sumr[x]+deep[u];
    		dfs(u);
    	}
    }
    bool issub(int x,int y){
    	return l[y]<=l[x] && r[x]<=r[y]; 
    }
    ll call(int u,int x){
    	ll ans=suml[x]+(ll)deep[u]*sl[x];
    	int lca=LCA(u,x);
    	ll now=(ll)(sl[x]-sl[lca])*deep[lca];
    	if (issub(u,rs[lca]) && lca!=x) now++;
    	now=now+suml[lca]-sl[lca];
    	return ans-now*2;
    }
    ll calr(int u,int x){
    	ll ans=sumr[x]+(ll)deep[u]*sr[x];
    	int lca=LCA(u,x);
    	ll now=(ll)(sr[x]-sr[lca])*deep[lca];
    	if (issub(u,ls[lca]) && lca!=x) now++;
    	now=now+sumr[lca]-sr[lca];
    	return ans-now*2;
    }
    ll solve(int u,int L,int R){
    	int lca=LCA(L,R);
    	return call(u,L)-call(u,ls[lca])+calr(u,R)-calr(u,rs[lca]);
    }
    int main(){
    	scanf("%d",&n);
    	build(0,1,n);
    	pos[0]=++cnt;
    	f[cnt][0]=cnt+1;//0
    	rt=++cnt;
    	l[rt]=0,r[rt]=n+1;//0-n+1 
    	ls[rt]=pos[0],rs[rt]=cnt+1;
    	cnt++,f[cnt][0]=rt,l[cnt]=1,r[cnt]=n+1;//1-n+1
    	ls[cnt]=1,rs[cnt]=cnt+1;f[1][0]=cnt;
    	cnt++;l[cnt]=r[cnt]=n+1;pos[n+1]=cnt;
    	f[cnt][0]=cnt-1;//n+1-n+1
    	for (int i=1;i<=W;i++)
    		for (int j=1;j<=cnt;j++)
    			f[j][i]=f[f[j][i-1]][i-1];
    	dfs(rt);
    	scanf("%d",&Q);
    	while (Q--){
    		scanf("%d%d%d",&u,&L,&R);
    		L=pos[L-1],R=pos[R+1];
    		printf("%lld
    ",solve(u,L,R));
    	}
    } 
    
    * 生而自由 爱而无畏 *
  • 相关阅读:
    jQuery1.3.2 源码学习 2 两个重要的正则表达式
    学习 jQuery 4 使用方法选择
    学习 jQuery 6 在 TreeView 中实现全选
    jQuery1.3.2 源码学习4 init 函数分析 2
    学习 jQuery 3 选择器
    学习 jQuery 5 筛选和过滤器
    条款9:在删除选项中仔细选择
    优化3D图形流水线
    指针相减
    浅谈水体的实现
  • 原文地址:https://www.cnblogs.com/flyfeather6/p/14381025.html
Copyright © 2020-2023  润新知