zoukankan      html  css  js  c++  java
  • BZOJ 2212 [Poi2011]Tree Rotations

    题解:交换某节点的两棵子树仅对   此节点子树对答案的贡献   有影响

    Dfs,启发式合并时顺便求逆序对即可,贪心交不交换

    O(nlogn*logn)

    Noname讲过一种合并Treap求逆序对,仅需O(nlogn),还不会

    注意:插入时维护路径上的siz,插入完Splay到根节点的儿子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    const int maxn=300009;
    
    int n;
    long long ans;
    
    int nn;
    int fa[maxn],ch[maxn][2],siz[maxn],ky[maxn];
    inline int son(int x){
    	if(ch[fa[x]][0]==x)return 0;
    	else return 1;
    }
    void pushup(int x){
    	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    }
    
    inline void Rotate(int x){
    	int y=fa[x];
    	int z=fa[y];
    	int b=son(x),c=son(y);
    	int a=ch[x][b^1];
    	if(z)ch[z][c]=x;
    	fa[x]=z;
    	if(a)fa[a]=y;
    	ch[y][b]=a;
    	fa[y]=x;ch[x][b^1]=y;
    	pushup(y);pushup(x);
    }
    
    void Splay(int x,int i){
    	while(fa[x]!=i){
    		int y=fa[x];
    		int z=fa[y];
    		if(z==i){
    			Rotate(x);
    		}else{
    			if(son(x)==son(y)){
    				Rotate(y);Rotate(x);
    			}else{
    				Rotate(x);Rotate(x);
    			}
    		}
    	}
    }
    
    int Ins(int p,int root){
    	int ret=0;
    	int x=root,y=0;
    	while(x){
    		siz[x]++;
    		y=x;
    		if(ky[p]>ky[x]){
    			ret+=siz[ch[x][0]]+1;
    			x=ch[x][1];
    		}else{
    			x=ch[x][0];
    		}
    	}
    	x=p;
    	fa[x]=y;ch[x][0]=ch[x][1]=0;siz[x]=1;
    	if(y){
    		if(ky[x]>ky[y])ch[y][1]=x;
    		else ch[y][0]=x;
    	}
    	Splay(x,root);
    	return ret;
    }
    
    long long Mer(int x,int root){
    	long long ret=0;
    	int rs=ch[x][1];
    	if(ch[x][0])ret+=Mer(ch[x][0],root);
    	ret+=Ins(x,root);
    	if(rs)ret+=Mer(rs,root);
    	return ret;
    }
    
    //int Getsmall(int val,int root){
    //	int ret=0,x=root;
    //	while(x){
    //		if(val>ky[x]){
    //			ret+=siz[ch[x][0]]+1;
    //			x=ch[x][1];
    //		}else{
    //			x=ch[x][0];
    //		}
    //	}
    //	return ret;
    //}
    
    //long long Tong(int x,int root){
    //	long long ret=0;
    //	ret=Getsmall(ky[x],root);
    //	if(ch[x][0])ret+=Tong(ch[x][0],root);
    //	if(ch[x][1])ret+=Tong(ch[x][1],root);
    //	return ret;
    //}
    
    int Dfs(){
    	int r;
    	scanf("%d",&r);
    	if(r){
    		++nn;
    		fa[nn]=ch[nn][0]=ch[nn][1]=0;
    		ky[nn]=r;siz[nn]=1;
    		return nn;
    	}else{
    		int x=Dfs();
    		int y=Dfs();
    		long long tm=0,tm2=0;
    		long long sizx=siz[x];
    		long long sizy=siz[y];
    		if(siz[x]<siz[y]){
    			tm=Mer(x,y)-sizx*(sizx-1)/2;
    			tm2=sizx*sizy-tm;
    			ans+=min(tm,tm2);
    		}else{
    			tm=sizx*sizy-(Mer(y,x)-sizy*(sizy-1)/2);
    			tm2=sizx*sizy-tm;
    			ans+=min(tm,tm2);
    		}
    		Splay(x,0);
    		return x;
    	}
    }
    
    int main(){
    	scanf("%d",&n);
    	Dfs();
    	printf("%lld
    ",ans);
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    获得 Web Service 方法的描述信息
    make menuconfig 报错
    汇编调用c函数为什么要设置栈
    UBoot Makefile文件分析
    UBoot启动过程完全分析(转)
    (转)在fedora12下用crosstoolng建立armlinux交叉编译环境
    UBoot编译过程完全分析(转)
    雷军:给互联网创业者的“七字”建议
    uboot根目录下makefile
    Redhat 5 配置Samba服务器
  • 原文地址:https://www.cnblogs.com/zzyer/p/8481101.html
Copyright © 2011-2022 走看看