wikioi1688 求逆序对

平衡树 同时被 2 个专栏收录
5 篇文章 0 订阅
12 篇文章 0 订阅

给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目

 

数据范围:N<=105Ai<=105。时间限制为1s。


第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。

所有逆序对总数.

4

3

2

3

2

3

感觉我又刷起水题了……

用归并排序线段树树状数组的都太low了

看我用treap搞之

每次询问比它大的有多少个,然后插入就好了

#include<cstdio>
#include<cstdlib>
#include<ctime>
#define LL long long
using namespace std;
struct SBT{
	int l,r,dat,rnd,rep,son;
}tree[200010];
int n,treesize,root;
LL ans;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void update(int k)
{
	tree[k].son=tree[k].rep+tree[tree[k].l].son+tree[tree[k].r].son;
}
inline void right_rotate(int &k)
{
	int t=tree[k].l;
	tree[k].l=tree[t].r;
	tree[t].r=k;
	tree[t].son=tree[k].son;
	update(k);
	k=t;
}
inline void left_rotate(int &k)
{
	int t=tree[k].r;
	tree[k].r=tree[t].l;
	tree[t].l=k;
	tree[t].son=tree[k].son;
	update(k);
	k=t;
}
inline void insert(int &k,int x)
{
	if(!k)
	{
		k=++treesize;
		tree[k].dat=x;
		tree[k].rep=1;
		tree[k].son=1;
		return;
	}
	tree[k].son++;
	if (tree[k].dat==x)
	{
		tree[k].rep++;
		return;
	}
	if(x<tree[k].dat)
	{
		insert(tree[k].l,x);
		if(tree[tree[k].l].rnd>tree[k].rnd)right_rotate(k);
	}else
	{
		insert(tree[k].r,x);
		if(tree[tree[k].r].rnd>tree[k].rnd)left_rotate(k);
	}
}
inline int query(int k,int x)
{
	if (!k)return 0;
	if (tree[k].dat>x)return tree[k].rep+tree[tree[k].r].son+query(tree[k].l,x);
	if (tree[k].dat==x)return query(tree[k].r,x);
	if (tree[k].dat<x)return query(tree[k].r,x);
}
int main()
{
	n=read();
	for (int i=1;i<=n;i++)
	{
		int x=read();
		ans+=query(root,x);
		insert(root,x);
	}
	printf("%lld\n",ans);
}

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值