题目描述 Description
给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目
数据范围:N<=105。Ai<=105。时间限制为1s。
输入描述 Input Description
第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。
输出描述 Output Description
所有逆序对总数.
样例输入 Sample Input
4
3
2
3
2
样例输出 Sample Output
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 ",ans); }