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