给出一个二叉树,叶子结点上有权值;
共有n个叶子结点,权值分别为1-n;
现可将所有结点的左右儿子交换,求最小的逆序对数;
2<=n<=200000;
题解:
这题读入有点鬼畜,但是写起来还是比较优雅的;
考虑到一个结点的子树具体形态与它是否和它的兄弟交换是无关的;
所以我们可以像分治一样,先计算子树之间的最小逆序对数;
然后将所有的权值扔到一个线段树中,向它的父亲传递;
它的父亲是没有权值的,我们只是在这里计算这两个线段树之间最小逆序对数,并将其合并就好了;
具体实现实际上只是一个合并操作中多了两个记录,考虑左子树与右子树是否交换;
对于一个线段树上的结点,我们累加:
左子树<=mid的结点数*右子树>mid的结点数作为左子树与右子树交换的逆序对数;
左子树>mid的结点数*右子树<=mid的结点数作为左子树与右子树不交换的逆序对数;
然后合并完成之后比较一下,累加到答案里就可以了;
答案可能超过int,时间复杂度O(nlogn)吧。。。
内存似乎比较玄学,应该是不超过nlogn的(空间复杂度不会大过时间复杂度呢);
代码:
#include<cctype> #include<stdio.h> #include<string.h> #include<algorithm> #define N 210000 #define M 3000000 #define LEN 1<<15 #define lson l,mid,ls[no] #define rson mid+1,r,rs[no] using namespace std; typedef long long ll; int sum[M],ls[M],rs[M],tot; int st[M],top,n; ll ans; char getc() { static char *S,*T,buf[LEN]; if(S==T) { T=(S=buf)+fread(buf,1,LEN,stdin); if(S==T) return EOF; } return *S++; } int read() { static char ch; static int D; while(!isdigit(ch=getc())); for(D=ch-'0';isdigit(ch=getc());) D=D*10+ch-'0'; return D; } int newnode() { if(top) return st[top--]; return ++tot; } void delnode(int no) { st[++top]=no; sum[no]=ls[no]=rs[no]=0; } void Pushup(int no) { sum[no]=sum[ls[no]]+sum[rs[no]]; } void Insert(int l,int r,int &no,int val) { if(!no) no=newnode(); if(l==r) sum[no]++; else { int mid=l+r>>1; if(val<=mid)Insert(lson,val); else Insert(rson,val); Pushup(no); } } int merge(int l,int r,int nol,int nor,ll &cntl,ll &cntr) { if(!nol||!nor) return nol+nor; cntl+=(ll)sum[rs[nol]]*sum[ls[nor]]; cntr+=(ll)sum[ls[nol]]*sum[rs[nor]]; int mid=l+r>>1,no=newnode(); ls[no]=merge(l,mid,ls[nol],ls[nor],cntl,cntr); rs[no]=merge(mid+1,r,rs[nol],rs[nor],cntl,cntr); Pushup(no); delnode(nol),delnode(nor); return no; } int dfs() { int x; x=read(); if(!x) { int ls=dfs(); int rs=dfs(); if(sum[ls]>sum[rs]) swap(ls,rs); ll cntl=0,cntr=0; int rt=merge(1,n,ls,rs,cntl,cntr); ans+=min(cntl,cntr); return rt; } else { int rt=0; Insert(1,n,rt,x); return rt; } } int main() { n=read(); dfs(); printf("%lld\n",ans); return 0; }
原文地址:http://blog.csdn.net/ww140142/article/details/48826481