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. Android OpenSL ES 开发:使用 OpenSL 播放 PCM 数据

    OpenSL ES 是基于NDK也就是c语言的底层开发音频的公开API,通过使用它能够做到标准化, 高性能,低响应时间的音频功能实现方法. 这次是使用OpenSL ES来做一个音乐播放器,它能够播放m ...

  2. ThreadLocal及InheritableThreadLocal的原理剖析

    我们知道,线程的不安全问题,主要是由于多线程并发读取一个变量而引起的,那么有没有一种办法可以让一个变量是线程独有的呢,这样不就可以解决线程安全问题了么.其实JDK已经为我们提供了ThreadLocal ...

  3. [Swift]LeetCode242. 有效的字母异位词 | Valid Anagram

    Given two strings s and t , write a function to determine if t is an anagram of s. Example 1: Input: ...

  4. [Swift]LeetCode250.计数相同值子树的个数 $ Count Univalue Subtrees

    Given a binary tree, count the number of uni-value subtrees. A Uni-value subtree means all nodes of ...

  5. [Swift]LeetCode371. 两整数之和 | Sum of Two Integers

    Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. Exam ...

  6. [Swift]LeetCode488. 祖玛游戏 | Zuma Game

    Think about Zuma Game. You have a row of balls on the table, colored red(R), yellow(Y), blue(B), gre ...

  7. [Swift]LeetCode913.猫与老鼠 | Cat and Mouse

    A game on an undirected graph is played by two players, Mouse and Cat, who alternate turns. The grap ...

  8. [Swift]LeetCode975. 奇偶跳 | Odd Even Jump

    You are given an integer array A.  From some starting index, you can make a series of jumps.  The (1 ...

  9. 微信小程序入门(五)

    24.MINA框架讲解 MINA框架架构 25.小程序运行机制 小程序在首次打开的时间会比较长,后续再打开启动会很快,那么小程序是如何启动的呢? 运行机制-启动 冷启动 热启动 热启动:假入用户已经打 ...

  10. 在ASP.NET Core中获取客户端IP地址

    随着ASP.NET的发展,有不同的方式从请求中访问客户端IP地址.WebForms和MVC Web应用程序只是访问当前HTTP上下文的请求. var ip = HttpContext.Current. ...