• 【题解】[POI2011]ROT-Tree Rotations


    Problem

    ( ext{Solution:})

    这东西的输入有些新奇,写一个递归函数即可。

    观察到题目要求的是子树交换,没有修改。而且,显然地,这样的结构必然要满足对于它每一个子结构都达到最优。而且任意一棵子树内部交换对答案的影响是独立的。

    考虑从下往上维护答案,每次需要合并两棵子树的信息并选择小的逆序对。

    合并信息,自然想到了线段树合并。

    考虑如何在线段树合并的时候计算出逆序对:用类似于 cdq分治 的思想,考虑计算跨越区间的答案:用位置靠前的节点数乘位置靠后的节点数,并同时满足前面的数小于后面的。然后再分别递归处理子树(左右区间)。

    这样就可以做到一只 $log $ 了。

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=5e6+10;
    int n,root,rt[MAXN],cnt;
    int ls[MAXN],rs[MAXN],sum[MAXN];
    int node,pa[MAXN],tot,head[MAXN];
    long long K1,K2,ans[MAXN];
    inline int read(){
    	int s=0;
    	char ch=getchar();
    	while(!isdigit(ch))ch=getchar();
    	while(isdigit(ch)){
    		s=s*10-48+ch;
    		ch=getchar();
    	}
    	return s;
    }
    inline long long Min(long long x,long long y){return x<y?x:y;}
    struct E{int nxt,to;}e[MAXN];
    inline void add(int x,int y){e[++tot]=(E){head[x],y};head[x]=tot;}
    inline void pushup(int x){sum[x]=sum[ls[x]]+sum[rs[x]];}
    void change(int &x,int L,int R,int pos,int v){
    	if(!x)x=++node;
    	if(L==R){
    		sum[x]+=v;
    		return;
    	}
    	int mid=(L+R)>>1;
    	if(pos<=mid)change(ls[x],L,mid,pos,v);
    	else change(rs[x],mid+1,R,pos,v);
    	pushup(x);
    }
    int merge(int x,int y,int l,int r,int pos){
    	if(!x||!y)return x+y;
    	if(l==r){sum[x]+=sum[y];return x;}
    	int mid=(l+r)>>1;
    	K1+=1ll*sum[rs[x]]*sum[ls[y]];
    	K2+=1ll*sum[ls[x]]*sum[rs[y]];
    	ls[x]=merge(ls[x],ls[y],l,mid,pos);
    	rs[x]=merge(rs[x],rs[y],mid+1,r,pos);
    	pushup(x);return x;
    }
    void Read(int &x){
    	if(!x)x=++cnt;
    	int v=read();
    	if(v==0){
    		int lson=0;
    		Read(lson);
    		int rson=0;
    		Read(rson);
    		pa[lson]=pa[rson]=x;
    		add(lson,x);add(rson,x);
    		add(x,lson);add(x,rson);
    	}
    	else {
    		change(rt[x],1,n,v,1);
    		ans[x]=0;
    		return;
    	}
    }
    void dfs(int x){
    	for(int i=head[x];i;i=e[i].nxt){
    		int j=e[i].to;
    		if(j==pa[x])continue;
    		dfs(j);
    		K1=K2=0;
    		rt[x]=merge(rt[x],rt[j],1,n,x);
    		ans[x]=Min(K1,K2);
    	}
    }
    int main(){
    	n=read();
    	Read(root);
    	dfs(root);
    	long long res=0;
    	for(int i=1;i<=cnt;++i)res+=ans[i];
    	printf("%lld
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    Python之禅
    浅析css布局模型1
    原型与继承学习笔记4
    原型与继承学习笔记3
    原型与继承学习笔记1
    javascript-this,call,apply,bind简述3
    javascript-this,call,apply,bind简述2
    javascript-this,call,apply,bind简述1
    javascript数组浅谈3
    javascript数组浅谈2
  • 原文地址:https://www.cnblogs.com/h-lka/p/14956023.html
Copyright © 2020-2023  润新知