zoukankan      html  css  js  c++  java
  • P3521 [POI2011]ROT-Tree Rotations

    题解

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

    可以发现交换某个点 (u) 的代价可以快速计算:在把左、右儿子的线段树合并上来的时候,对于这两棵线段树上的对应点 (p,q),不交换的代价会增加 (v_{mathrm{rson}(p)} imes v_{mathrm{lson}(q)}),交换的代价会增加 (v_{mathrm{lson}(p)} imes 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
    ",Solve(1,temp));
    	return 0;
    }
    
    Written by Alan_Zhao
  • 相关阅读:
    PostgreSQL的数据类型
    博客园背景页面动态特效
    css ie7中overflow:hidden失效问题及解决方法
    win10的安装、win10启动盘制作
    windows win7 win10 多系统启动菜单 多系统引导设置
    微博加关注按钮
    {转}一位北京差生9年的北京生活
    最全的CSS浏览器兼容问题
    网站开发命名详细规范
    <meta http-equiv = "X-UA-Compatible" cotent = "IE=edge,chrome=1"/>
  • 原文地址:https://www.cnblogs.com/alan-zhao-2007/p/p3521-sol.html
Copyright © 2011-2022 走看看