震惊!Vector两行代码求逆序对,六行代码过普通平衡树

Posted 自为

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了震惊!Vector两行代码求逆序对,六行代码过普通平衡树相关的知识,希望对你有一定的参考价值。

Vector两行代码求逆序对

背景:济南集训Day7上午T2,出了一道逆序对的裸题,SB的我没看出是逆序对来,于是现场推了一个很刁钻的求逆序对的方法

首先我们想一下冒泡排序的过程,我们不难发现,对于每一个元素,我们实际上是让他不停的和前面的元素比较,交换。

也正是因为这个过程决定了在冒泡排序的过程中:一个位置的数的前面的数一定是递增的(从小到大排的话)

那么我们在交换的时候,直接二分找到一个合适的位置,插入即可

这个很显然可以用平衡树Vector实现

代码也非常短,

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<vector>
 4 using namespace std;
 5 int n,m,ans,a[100001];
 6 vector<int>v;
 7 int main()
 8 {
 9     scanf("%d",&n);
10     for(int i=1;i<=n;i++)    scanf("%d",&a[i]);
11     for(int i=1;i<=n;i++)
12     {
13         int now=upper_bound(v.begin(),v.end(),a[i])-v.begin();
14         ans=ans+i-now-1,v.insert(v.begin()+now,a[i]);
15     }
16     printf("%d",ans);
17     return 0;
18 }

 

 

Vector六行代码过平衡树

这个参考了一下黄学长的博客,不过我没有用迭代器实现

顺便精简了一下代码

代码应该比较容易懂,就不细讲了

 1 #include<cstdio>
 2 #include<vector>
 3 #include<algorithm>
 4 using namespace std;
 5 vector<int>v;
 6 int n,opt,x;
 7 int main()
 8 {
 9     v.reserve(100001);
10     scanf("%d",&n);
11     while(n--)
12     {
13         scanf("%d%d",&opt,&x);
14         if(opt==1)    v.insert(lower_bound(v.begin(),v.end(),x),x);
15         if(opt==2)    v.erase (lower_bound(v.begin(),v.end(),x));
16         if(opt==3)    printf("%d\n",lower_bound(v.begin(),v.end(),x)-v.begin()+1);
17         if(opt==4)    printf("%d\n",v[x-1]);
18         if(opt==5)    printf("%d\n",v[lower_bound(v.begin(),v.end(),x)-v.begin()-1]);
19         if(opt==6)    printf("%d\n",v[upper_bound(v.begin(),v.end(),x)-v.begin()]);
20     }
21     return 0;
22 }

 

总的来说

Vector是个好东西,

试想一下如果未来每场考试都开O2的话,

数组这个东西会不会就消失了?

 

以上是关于震惊!Vector两行代码求逆序对,六行代码过普通平衡树的主要内容,如果未能解决你的问题,请参考以下文章

求数组的逆序对

求逆序对

求逆序对(树状数组)

一道编程题:求逆序对的个数

归并排序C++实现及求逆序对的个数

树状数组求逆序对