Loading

P3521 [POI2011]ROT-Tree Rotations - 线段树合并

题解

考虑对于每个点都开一棵动态开点线段树,以点权为下标、个数为值,记录以这个点为根的子树内的信息。

可以发现交换某个点 \(u\) 的代价可以快速计算:在把左、右儿子的线段树合并上来的时候,对于这两棵线段树上的对应点 \(p,q\),不交换的代价会增加 \(v_{\mathrm{rson}(p)}\times v_{\mathrm{lson}(q)}\),交换的代价会增加 \(v_{\mathrm{lson}(p)}\times v_{\mathrm{rson}(q)}\)。因为每个点选择是否交换对其祖先节点并无影响,所以每个点都贪心地选择代价最小的方案即可。

代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <vector>
using namespace std;
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
template<typename T> void Read(T &x){
	x=0;int _f=1;
	char ch=getchar();
	while(!isdigit(ch)) _f=(ch=='-'?-1:_f),ch=getchar();
	while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
	x=x*_f;
}
template<typename T,typename... Args> void Read(T &x,Args& ...others){
	Read(x);Read(others...);
}
typedef long long ll;
const int N=6e5+5;
int n,leaf,son[N][2],w[N];
int ReadTree(){
	int x,u=++n;Read(x);
	if(x) w[u]=x;
	else{
		son[u][0]=ReadTree();son[u][1]=ReadTree();
	}
	return u;
}
#define ls(xx) t[xx].ls
#define rs(xx) t[xx].rs
int tot=0;
struct Node{
	int l,r,ls,rs,v;
}t[N*18];
int Newnode(int l,int r){
	t[++tot]=Node{l,r,0,0,0};
	return tot; 
}
void Pushup(int p){t[p].v=t[ls(p)].v+t[rs(p)].v;}
void Add(int p,int pos,int x){
	if(t[p].l==t[p].r){
		t[p].v+=x;return;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(pos<=mid){
		if(!ls(p)) ls(p)=Newnode(t[p].l,mid);
		Add(ls(p),pos,x);
	}else{
		if(!rs(p)) rs(p)=Newnode(mid+1,t[p].r);
		Add(rs(p),pos,x);
	}
	Pushup(p);
}
int Merge(int u,int v,ll &x,ll &y){
	if(!u||!v) return u^v;
	if(t[u].l==t[u].r){t[u].v+=t[v].v;return u;}
	x+=1LL*t[rs(u)].v*t[ls(v)].v,y+=1LL*t[rs(v)].v*t[ls(u)].v;
	ls(u)=Merge(ls(u),ls(v),x,y),rs(u)=Merge(rs(u),rs(v),x,y);
	Pushup(u);return u;
}
ll Solve(int u,int &rt){
	if(w[u]){
		rt=Newnode(1,leaf);
		Add(rt,w[u],1);return 0;
	}
	int rt1,rt2;ll x=0,y=0,res=0;
	res+=Solve(son[u][0],rt1);res+=Solve(son[u][1],rt2);
	rt=Merge(rt1,rt2,x,y);
	return res+min(x,y);
}
int main(){
	Read(leaf);ReadTree();
	int temp;
	printf("%lld\n",Solve(1,temp));
	return 0;
}
posted @ 2021-06-18 22:45  Alan_Zhao_2007  阅读(41)  评论(0编辑  收藏  举报