Vector两行代码求逆序对

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

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

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

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

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

代码也非常短,

 #include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int n,m,ans,a[];
vector<int>v;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=n;i++)
{
int now=upper_bound(v.begin(),v.end(),a[i])-v.begin();
ans=ans+i-now-,v.insert(v.begin()+now,a[i]);
}
printf("%d",ans);
return ;
}

update in 2017.12.16

补一发splay

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=1e6+;
const int maxn=0x7fffff;
inline char nc()
{
static char buf[MAXN],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
char c=nc();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=nc();}
while(c>=''&&c<=''){x=x*+c-'';c=nc();}
return x*f;
}
#define root tree[0].ch[1]
struct node
{
int v,fa,ch[],rec,sum;
};
node tree[MAXN];
int pointnum,tot;
int iden(int x){return tree[tree[x].fa].ch[]==x?:;}
inline void connect(int x,int fa,int how){tree[x].fa=fa;tree[fa].ch[how]=x;}
inline void update(int x){tree[x].sum=tree[tree[x].ch[]].sum+tree[tree[x].ch[]].sum+tree[x].rec;}
inline void rotate(int x)
{
int y=tree[x].fa;
int R=tree[y].fa;
int Rson=iden(y);
int yson=iden(x);
int b=tree[x].ch[yson^];
connect(b,y,yson);
connect(y,x,yson^);
connect(x,R,Rson);
update(y);update(x);
}
void splay(int pos,int to)// 把编号为pos的节点旋转到编号为to的节点
{
to=tree[to].fa;
while(tree[pos].fa!=to)
{
if(tree[tree[pos].fa].fa==to) rotate(pos);
else if(iden(tree[pos].fa)==iden(pos)) rotate(tree[pos].fa),rotate(pos);
else rotate(pos),rotate(pos);
}
}
inline int newpoint(int v,int fa)//
{
tree[++tot].fa=fa;
tree[tot].v=v;
tree[tot].sum=tree[tot].rec=;
return tot;
}
inline void dele(int x)
{
tree[x].ch[]=tree[x].ch[]=;
if(x==tot) tot--;
}
int find(int v)
{
int now=root;
while()
{
if(tree[now].v==v) {splay(now,root);return now;}
int nxt=v<tree[now].v?:;
if(!tree[now].ch[nxt])return ;
now=tree[now].ch[nxt];
}
}
int build(int v)
{
pointnum++;
if(tot==){root=;newpoint(v,);}
else
{
int now=root;
while()
{
tree[now].sum++;
if(tree[now].v==v){tree[now].rec++;return now;}//出现过
int nxt=v<tree[now].v?:;
if(!tree[now].ch[nxt])
{
newpoint(v,now);
tree[now].ch[nxt]=tot;
return tot;
}
now=tree[now].ch[nxt];
}
}
return ;
}
inline void insert(int v)
{
int p=build(v);//p代表插到了哪里
splay(p,root);
}
void pop(int v)
{
int deal=find(v);
if(!deal) return ;
pointnum--;
if(tree[deal].rec>){tree[deal].rec--;tree[deal].sum--;return ;}
if(!tree[deal].ch[]) root=tree[deal].ch[],tree[root].fa=;
else
{
int le=tree[deal].ch[];
while(tree[le].ch[]) le=tree[le].ch[];
splay(le,tree[deal].ch[]);
int ri=tree[deal].ch[];
connect(ri,le,);connect(le,,);
update(le);
}
dele(deal);
}
int rank(int v)// 查询值为v的数的排名
{
int ans=,now=root;
while()
{
if(tree[now].v==v) return ans+tree[tree[now].ch[]].sum+;
if(now==) return ;
if(v<tree[now].v) now=tree[now].ch[];
else ans+=tree[tree[now].ch[]].sum+tree[now].rec,now=tree[now].ch[];
}
if(now) splay(now,root);
return ;
}
int arank(int x)//查询排名为x的数是什么
{
int now=root;
while()
{
int used=tree[now].sum-tree[tree[now].ch[]].sum;
if(x>tree[tree[now].ch[]].sum&&x<=used) break;
if(x<used) now=tree[now].ch[];
else x=x-used,now=tree[now].ch[];
}
splay(now,root);
return tree[now].v;
}
int lower(int v)// 小于v的最大值
{
int now=root;
int ans=-maxn;
while(now)
{
if(tree[now].v<v&&tree[now].v>ans) ans=tree[now].v;
if(v>tree[now].v) now=tree[now].ch[];
else now=tree[now].ch[];
}
return ans;
}
int upper(int v)
{
int now=root;
int ans=maxn;
while(now)
{
if(tree[now].v>v&&tree[now].v<ans) ans=tree[now].v;
if(v<tree[now].v) now=tree[now].ch[];
else now=tree[now].ch[];
}
return ans;
}
int a[MAXN],n,ans=;
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
n=read();
for(int i=;i<=n;i++) a[i]=read();
for(int i=;i<=n;i++)
{
insert(a[i]);
int now=rank(a[i]);
if(i==) continue;
ans=ans+i-now;
}
printf("%d",ans);
}

Vector六行代码过平衡树

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

顺便精简了一下代码

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

 #include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
vector<int>v;
int n,opt,x;
int main()
{
v.reserve();
scanf("%d",&n);
while(n--)
{
scanf("%d%d",&opt,&x);
if(opt==) v.insert(lower_bound(v.begin(),v.end(),x),x);
if(opt==) v.erase (lower_bound(v.begin(),v.end(),x));
if(opt==) printf("%d\n",lower_bound(v.begin(),v.end(),x)-v.begin()+);
if(opt==) printf("%d\n",v[x-]);
if(opt==) printf("%d\n",v[lower_bound(v.begin(),v.end(),x)-v.begin()-]);
if(opt==) printf("%d\n",v[upper_bound(v.begin(),v.end(),x)-v.begin()]);
}
return ;
}

总的来说

Vector是个好东西,

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

数组这个东西会不会就消失了?Σ( ° △ °|||)︴

震惊!Vector两行代码求逆序对,六行代码过普通平衡树的更多相关文章

  1. POJ-2299 Ultra-QuickSort---树状数组求逆序对+离散化

    题目链接: https://vjudge.net/problem/POJ-2299 题目大意: 本题要求对于给定的无序数组,求出经过最少多少次相邻元素的交换之后,可以使数组从小到大有序. 两个数(a, ...

  2. 用归并排序或树状数组求逆序对数量 poj2299

    题目链接:https://vjudge.net/problem/POJ-2299 推荐讲解树状数组的博客:https://blog.csdn.net/int64ago/article/details/ ...

  3. POJ 2299 Ultra-QuickSort 离散化加树状数组求逆序对

    http://poj.org/problem?id=2299 题意:求逆序对 题解:用树状数组.每读入一个数x,另a[x]=1.那么a数列的前缀和s[x]即为x前面(或者说,再x之前读入)小于x的个数 ...

  4. 4163 hzwer与逆序对 (codevs + 权值线段树 + 求逆序对)

    题目链接:http://codevs.cn/problem/4163/ 题目:

  5. 归并排序+归并排序求逆序对(例题P1908)

    归并排序(merge sort) 顾名思义,这是一种排序算法,时间复杂度为O(nlogn),时间复杂度上和快排一样 归并排序是分治思想的应用,我们先将n个数不断地二分,最后得到n个长度为1的区间,显然 ...

  6. codeforces 540E 离散化技巧+线段树/树状数组求逆序对

    传送门:https://codeforces.com/contest/540/problem/E 题意: 有一段无限长的序列,有n次交换,每次将u位置的元素和v位置的元素交换,问n次交换后这个序列的逆 ...

  7. 2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对)

    2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对) https://www.luogu.com.cn/problem/P5041 题意: 给一个字符串 \(S\) ,每 ...

  8. HDU 3743 Frosh Week(归并排序求逆序对)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 题目意思就是给你一个长为n的序列,让你求逆序对.我用的是归并排序来求的.归并排序有一个合并的过程 ...

  9. AC日记——codevs 1688 求逆序对

    1688 求逆序对  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 给定一个序列a1,a2,…, ...

随机推荐

  1. c# 钩子类

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using S ...

  2. [Swift]LeetCode320. 通用简写 $ Generalized Abbreviation

    Write a function to generate the generalized abbreviations of a word. Example: Given word = "wo ...

  3. [Swift]LeetCode338. 比特位计数 | Counting Bits

    Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the ...

  4. [Swift]LeetCode414. 第三大的数 | Third Maximum Number

    Given a non-empty array of integers, return the third maximum number in this array. If it does not e ...

  5. [Swift]LeetCode575. 分糖果 | Distribute Candies

    Given an integer array with even length, where different numbers in this array represent different k ...

  6. layui.table图片显示不全和404问题

    1.图片显示不全 在使用layui.table组件中,加载的图片显示不全,需重新定义CSS如下: .layui-table-cell{ height: auto!important; white-sp ...

  7. HTML入门教程,多年心血总结,一看就会

    笔者在武汉蚂蹄软件服务中心做软件开发多年,最近花一天时间总结出一套HTML入门级的教程,全篇没有任何废话,全部是精华,希望对你入门web开发有一定的帮助. HTML基本格式 <html> ...

  8. python之高阶函数和匿名函数

    map() map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回. def func(x): return ...

  9. Kubernetes系列之理解K8s Service的几种模式

    今天给大家介绍下k8s的service的几种访问模式. 概述 我们知道pod的ip不是固定的,是根据所在宿主机的docker0网卡生成的,每次重启,更新,调度等情况IP都会变,那pod与pod之间需要 ...

  10. Paramiko模块简单使用

    介绍 Paramiko 一个第三方包,需要单独安装我们知道远程批量主机管理,比如ansible.Fabric,不需要安装客户端的远程执行命令等,这些都是基于Python原生的SSH,相当于模拟了一个S ...