离散化加树状数组求逆序数。
来源:互联网 发布:团子少女 知乎 编辑:程序博客网 时间:2024/06/10 01:59
【转自BLOG】点击打开链接
【1 POJ.2299】
离散化是一种常用的技巧,有时数据范围太大,可以用来放缩到我们能处理的范围 因为其中需排序的数的范围0---
999999999;显然数组不肯能这么大;而N的最大范围是500000;故给出的数一定可以与1.。。。N建立一个一一映射;
这里用一个结构体
struct Node
{
int v,order;
}a[510000];
和一个数组aa[510000];
其中v就是原输入的值,order是下标;然后对结构体按v从小到大排序;此时,v和结构体的下标就是一个一一对应关系,而且
满足原来的大小关系;
for(i=1;i<=N;i++)
aa[a[i].order]=i;
然后a数组就存储了原来所有的大小信息;比如 9 1 0 5 4 ------- 离散后aa数组就是 5 2 1 4 3;具体的过程可以自己
用笔写写就好了。
离散之后,怎么使用离散后的结果数组来进行树状数组操作,计算出逆序数?
如果数据不是很大,可以一个个插入到树状数组中,每插入一个数,统计比他小的数的个数,对应的逆序为 i- getsum(aa
[i]),其中i为当前已经插入的数的个数,getsum(aa[i])为比aa[i]小的数的个数,i- sum(aa[i]) 即比aa[i]大的个数,
即逆序的个数但如果数据比较大,就必须采用离散化方法。
【AC code】
//POJ.2299//Ultra-QuickSort#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn=500010;#define ll long longstruct node{ int v,order; friend bool operator<(const node &p,const node &q) { return p.v<q.v; }}a[maxn];//输入部分int aa[maxn];//离散化后的数组int c[maxn];//树状数组int n;void init(){ memset(c,0,sizeof(c));}int getsum(int i){ int s=0; while(i>0) { s+=c[i]; i-=i&-i; } return s;}void add(int i,int x){ while(i<=n) { c[i]+=x; i+=i&-i; }}int main(){ while(scanf("%d",&n)!=EOF) { if(n==0) break; for(int i=1; i<=n; i++) { scanf("%d",&a[i].v); a[i].order=i; } sort(a+1,a+n+1); for(int i=1; i<=n; i++) { aa[a[i].order]=i; } init(); ll ans=0; for(int i=1; i<=n; i++) { add(aa[i],1); ans+=i-getsum(aa[i]); } printf("%lld\n",ans); }}
【2 HDU.2492】
【题意】有两个人可以参加比赛,但是他们必须选一个裁判,并且这个裁判的能力值不能比这个人高,也不能比这个人低,求满足的方案数!对于每个人,只需要统计左边比他高,右边比他低的人数或者,统计左边比他低,右边比他高的人数,这两种选择的方案数之和就是整个的方案数。
【AC code】
//HDU.2492#include<cstdio>#include<cstring>#include<cmath>#include<cctype>#include<iostream>using namespace std;#define ll long longconst int maxn=100005;int a[maxn],b[maxn],c[maxn],d[maxn],e[maxn],f[maxn];int getInt(int &x){ return scanf("%d",&x);}int n;int low_bit(int x){ return x&(-x);}void update(int x,int v){ while(x<=maxn) { a[x]+=v; x+=low_bit(x); }}int get_sum(int x){ int sum=0; while(x>0) { sum+=a[x]; x-=low_bit(x); } return sum;}int main(){ int tt;ll ans; getInt(tt); while(tt--) { getInt(n); memset(a,0,sizeof(a)); ans=0; for(int i=1;i<=n;i++) { getInt(b[i]); } for(int i=1;i<=n;i++) { update(b[i],1); c[i]=get_sum(maxn)-get_sum(b[i]); //左边有多少个数比自己大 d[i]=get_sum(b[i]-1); //左边有多少个数比自己小 } memset(a,0,sizeof(a)); for(int i=n;i>=1;i--) { update(b[i],1); e[i]=get_sum(maxn)-get_sum(b[i]); //右边有多少个数比自己大 f[i]=get_sum(b[i]-1); //右边有多少个数比自己小 } for(int i=1;i<=n;i++) { ans+=c[i]*f[i]+d[i]*e[i]; } printf("%lld\n",ans); } return 0;}
- 离散化加树状数组求逆序数。
- 离散化+树状数组求逆序数
- 树状数组离散化求逆序数
- 树状数组+ 离散化 求逆序数
- 求逆序数(树状数组+离散)
- HDU5792(离散化+树状数组求逆序数)树状数组求逆序深入讲解
- POJ 2299 离散化+树状数组求逆序数
- POJ 2299 树状数组求逆序数+离散化
- poj 2299 离散化+树状数组求逆序数
- 离散化+树状数组 求逆序数POJ2299
- poj 2299(离散化+树状数组求逆序数)
- nyoj117求逆序数(离散化+树状数组/归并排序)
- poj 2299 树状数组求逆序数+离散化
- nyoj 117 求逆序数 【树状数组】+【离散化】
- Ultra-QuickSort(离散化+树状数组求逆序数)
- 树状数组求逆序数的模板(离散化处理)
- 树状数组+离散化 《求逆序数对》
- POJ 2299 <离散化+树状数组求逆序数对>
- 64位windows上访问64位oracle 12c
- 求两个字符串的编辑距离
- Java学习笔记之深入理解关键字super
- UVA-644 Immediate Decodability
- 网络流之SAP算法学习
- 离散化加树状数组求逆序数。
- 如何运行 Linux 下的软件?
- 如何减少换页错误?
- UVA10177(2/3/4)-D Sqr/Rects/Cubes/Boxes?
- 简单c/s程序(Linux c)
- UVa 1594(Ducci Sequence)
- 深入分析Java I/O 工作机制
- 关于控件的width或者height设置成"0dp"的原因
- STL迭代器(iterator)