[POI2011]Rotacje na drzewie (2)/[BZOJ3702]二叉树

[POI2011]Rotacje na drzewie (2)

题目大意:

一棵有\(n\)个叶子结点的二叉树,每个叶子结点有一个权值,恰好是\(1\sim n\)的一个排列,你可以任意交换每一对子结点,使得从左往右的权值序列中,逆序对数量最少,求最少逆序对数。

原题:\(n\le2\times10^5\),空间限制64MB;
加强版:\(n\le10^6\),空间限制128MB。

思路:

原题可以直接使用线段树合并,注意空间回收即可通过此题。

加强版可以使用pb_ds红黑树按秩和并。

源代码1:

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
typedef long long int64;
int n;
int64 cnt0,cnt1,ans;
struct Node {
	Node *left,*right;
	int sum;
	Node():left(NULL),right(NULL),sum(0) {}
};
inline int count(const Node *const &p) {
	return p?p->sum:0;
}
Node *build(const int &b,const int &e,const int &x) {
	Node *p=new Node;
	p->sum++;
	if(b==e) return p;
	const int mid=(b+e)>>1;
	if(x<=mid) p->left=build(b,mid,x);
	if(x>mid) p->right=build(mid+1,e,x);
	return p;
}
Node *merge(Node *p,Node *q,const int &b,const int &e) {
	if(!p||!q) return p?:q;
	p->sum+=q->sum;
	if(b==e) {
		delete q;
		return p;
	}
	const int mid=(b+e)>>1;
	cnt0+=(int64)count(p->left)*count(q->right);
	cnt1+=(int64)count(q->left)*count(p->right);
	p->left=merge(p->left,q->left,b,mid);
	p->right=merge(p->right,q->right,mid+1,n);
	delete q;
	return p;
}
Node* solve() {
	const int w=getint();
	if(w!=0) {
		return build(1,n,w);
	} else {
		Node *p=merge(solve(),solve(),1,n);
		ans+=std::min(cnt0,cnt1);
		cnt0=cnt1=0;
		return p;
	}
}
int main() {
	n=getint();
	solve();
	printf("%lld\n",ans);
	return 0;
}

源代码2:

#include<cstdio>
#include<cctype>
#include<functional>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
typedef __gnu_pbds::tree<int,__gnu_pbds::null_type,std::less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update> rbt;
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
typedef long long int64;
typedef unsigned long long uint64;
int n;
int64 ans;
inline rbt *merge(rbt *p,rbt *q) {
	if(p->size()<q->size()) std::swap(p,q);
	uint64 tmp=0;
	for(int x:*q) tmp+=p->order_of_key(x);
	ans+=std::min(1ll*p->size()*q->size()-tmp,tmp);
	for(int x:*q) p->insert(x);
	delete q;
	return p;
}
rbt *solve() {
	const int w=getint();
	if(w!=0) {
		rbt *p=new rbt;
		p->insert(w);
		return p;
	} else {
		return merge(solve(),solve());
	}
}
int main() {
	n=getint();
	solve();
	printf("%lld\n",ans);
	return 0;
}
posted @ 2018-10-16 15:34  skylee03  阅读(149)  评论(0编辑  收藏  举报