其他分享
首页 > 其他分享> > 洛谷 P3521 [POI2011]ROT-Tree Rotations

洛谷 P3521 [POI2011]ROT-Tree Rotations

作者:互联网

Description

洛谷传送门

Solution

线段树合并

显然,两棵树的交换与他们的子树无关,所以从下往上处理即可。

我们考虑对于每个子节点建一只权值线段树。然后不断向上合并。

注意:每个点都是一只完整的权值线段树,也就是说左子树权值小于右子树权值。

所以逆序对个数就很明显了。

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ls(x) t[x].l
#define rs(x) t[x].r
#define ll long long

using namespace std;

const int N = 4e6 + 10;
int n, cnt;
ll s1, s2, ans;
struct Seg_tree{
	int l, r, sum;
}t[N];

inline void update(int &x, int l, int r, int pos){
	if(!x) x = ++cnt;
	t[x].sum++;
	if(l == r) return;
	int mid = (l + r) >> 1;
	if(pos <= mid) update(ls(x), l, mid, pos);
	else update(rs(x), mid + 1, r, pos);
}

inline int merge(int u, int v, int l, int r){
	if(!u || !v) return u | v;
	t[u].sum += t[v].sum;
	s1 += 1ll * t[rs(u)].sum * t[ls(v)].sum;
	s2 += 1ll * t[ls(u)].sum * t[rs(v)].sum;
	int mid = (l + r) >> 1;
	ls(u) = merge(ls(u), ls(v), l, mid);
	rs(u) = merge(rs(u), rs(v), mid + 1, r);
	return u;
}

inline void dfs(int &x){
	int t;
	scanf("%d", &t);
	if(!t){
		int u = 0, v = 0;
		dfs(u), dfs(v);
		s1 = 0, s2 = 0;
		x = u;
		x = merge(x, v, 1, n);
		ans += min(s1, s2);
	}else update(x, 1, n, t);
}

int main(){
	scanf("%d", &n);
	int root = 0;
	dfs(root);
	printf("%lld\n", ans);
	return 0;
}

End

标签:洛谷,P3521,rs,int,s2,sum,Rotations,dfs,ls
来源: https://www.cnblogs.com/xixike/p/15369718.html