P3521 [POI2011]ROT-Tree Rotations

Posted syzf2222

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3521 [POI2011]ROT-Tree Rotations相关的知识,希望对你有一定的参考价值。

如果不算数组开小和没开(long long)的话,我又是一遍过的。

思路很简单,考虑在线段树合并的时候,计算逆序对的贡献。

假设合并线段树(a)(b),则在区间(left[l,r ight])的时候,

(a)在前所产生的逆序对个数为(a)的右子树的大小乘以(b)的左子树的大小。

(b)在前所产生的逆序对个数为(a)的左子树的大小乘以(b)的右子树的大小。

思想类似于(cdq)分治。

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=4e5+10;
int n,a[maxn],root,cnt,tot,ans;
int lson[maxn<<1],rson[maxn<<1],rt[maxn<<1];
struct node{
	int val,lc,rc;
}tr[maxn*20];
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
	while(c>=‘0‘&&c<=‘9‘){x=(x<<1)+(x<<3)+c-‘0‘;c=getchar();}
	return x*f;
}
inline int init(){
	int x=read(),lc,rc;
	if(x){a[++cnt]=x;return cnt;}
	lc=init();rc=init();
	++cnt;lson[cnt]=lc;rson[cnt]=rc;
	return cnt;
}
inline int update(int h,int l,int r,int x){
	if(!h)h=++tot;
	tr[h].val++;
	if(l==r)return h;
	int mid=(l+r)>>1;
	if(mid>=x)tr[h].lc=update(tr[h].lc,l,mid,x);
	else tr[h].rc=update(tr[h].rc,mid+1,r,x);
	return h;
}
int cnt1,cnt2,tot1,tot2;
inline int merge(int a,int b,int l,int r){
	if(!a)return b;
	if(!b)return a;
	cnt1+=tr[tr[a].lc].val*tr[tr[b].rc].val;
	cnt2+=tr[tr[a].rc].val*tr[tr[b].lc].val;
	tr[a].val+=tr[b].val;
	if(l==r)return a;
	int mid=(l+r)>>1;
	tr[a].lc=merge(tr[a].lc,tr[b].lc,l,mid);
	tr[a].rc=merge(tr[a].rc,tr[b].rc,mid+1,r);
	return a;
}
inline void dfs(int x){
	if(!lson[x]){
		rt[x]=update(rt[x],1,n,a[x]);
		return;
	}
	dfs(lson[x]);
	dfs(rson[x]);
	cnt1=cnt2=tot1=tot2=0;
	rt[x]=merge(rt[lson[x]],rt[rson[x]],1,n);
	ans+=min(cnt1,cnt2);
}
signed main(){
	n=read();
	root=init();
	dfs(root);
	printf("%lld
",ans);
	return 0;
}

深深地感到自己的弱小。

以上是关于P3521 [POI2011]ROT-Tree Rotations的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P3521 [POI2011]ROT-Tree Rotations

题解 P3521 [POI2011]ROT-Tree Rotations

「Luogu P3521 [POI2011]ROT-Tree Rotations」

LuoguP3521 [POI2011]ROT-Tree Rotations

bzoj 2212[POI2011]ROT-Tree Rotations - 线段树合并

[POI2011]ROT-Tree Rotations