HDU 1394 Minimum Inversion Number(线段树 或 树状数组)
题目大意:给出从 0 到 n-1 的整数序列,A0,A1,A2...An-1。可将该序列的前m( 0 <= m < n )个数移到后面去,组成其他的序列,例如当 m=2 时,得到序列 A2,A3...An-1,A0,A1 。我们定义逆序对<Ai,Aj>满足 i < j 且Ai > Aj 。 在所有的序列中找出逆序对最少的序列,输出逆序对个数。num[n+1]存储序列元素。
思路: 假设某个序列的逆序对个数为 sum 则下一个序列的逆序对个数为 sum - num[1] + (n - 1) - num[1]。则只需要求出原始序列的逆序对个数计科推出后面的所有序列的逆序对个数。
再输入每个元素的时候统计区间 [num[i]+1,n-1] 之间的元素已经能出现的总次数,则可以用线段树,或树状数组统计。下面给出两种方法的代码。
树状数组:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define INF 0x7fffffff
int a[5010],c[5010],n;
int lowbit(int x){
return x & (-x) ;
}
void add(int x,int d){
while(x <= n){
c[x] += d;
x = x + lowbit(x) ;
}
}
int getsum(int x){
int ans = 0;
while(x > 0){
ans += c[x] ;
x = x - lowbit(x) ;
}
return ans ;
}
int main(){
int i,j,x,num[5010];
while(~scanf("%d",&n) && n){
int sum = 0;
memset(c,0,sizeof(c));
for(i=1;i<=n;i++){
scanf("%d",&x) ;
num[i] = x ;
x ++ ;
sum += getsum(n) - getsum(x) ;
add(x,1);
}
int ans = sum ;
for(i=1;i<n;i++){
sum = sum - (num[i] + 1) + n - num[i] ;
ans = min(ans,sum);
}
cout << ans << endl;
}
return 0;
}
线段树
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define INF 0x7fffffff
int n,x;
struct node{
int l,r,sum;
}a[20100];
void buildtree(int i,int l,int r){
a[i].l = l ;
a[i].r = r;
a[i].sum = 0;
if(l == r)
return ;
int mid = (l+r)/2;
buildtree((i<<1),l,mid);
buildtree(i*2+1,mid+1,r);
}
int query(int i,int l,int r){
if(l>r)
return 0;
if(a[i].l == l && a[i].r == r)
return a[i].sum;
int sum = 0;
int mid = (a[i].l + a[i].r) / 2 ;
if(r<=mid)
sum = query(i*2,l,r);
else if(l > mid)
sum = query(i*2+1,l,r);
else
sum = query(i*2,l,mid) + query(i*2+1,mid+1,r) ;
return sum ;
}
void update(int i,int x){
if(a[i].l == x && a[i].r == x){
a[i].sum ++;
}
else{
a[i].sum ++;
int mid = (a[i].l + a[i].r) / 2 ;
if(x<=mid)
update(i*2,x);
else
update(i*2+1,x);
}
}
int main(){
int i,j,sum,num[5010];
while(~scanf("%d",&n) && n ){
sum = 0 ;
buildtree(1,0,n-1);
for(i=1;i<=n;i++){
scanf("%d",&x);
num[i] = x ;
sum += query(1,x+1,n-1);
update(1,x);
}
int ans = sum;
for(i=1;i<n;i++)
{
sum = sum - num[i] + n-num[i]-1 ;
ans = min(ans,sum);
}
cout << ans << endl ;
}
return 0;
HDU 1394 Minimum Inversion Number(线段树 或 树状数组)的更多相关文章
- HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)
HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...
- [HDU] 1394 Minimum Inversion Number [线段树求逆序数]
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- HDU 1394 Minimum Inversion Number (数据结构-段树)
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- hdu - 1394 Minimum Inversion Number(线段树水题)
http://acm.hdu.edu.cn/showproblem.php?pid=1394 很基础的线段树. 先查询在更新,如果后面的数比前面的数小肯定会查询到前面已经更新过的值,这时候返回的sum ...
- HDU 1394 Minimum Inversion Number 线段树
题目: http://acm.hdu.edu.cn/showproblem.php?pid=1394 没看到多组输入,WA了一万次...... 其实很简单,有人暴力过得,我感觉归并排序.二叉排序树求逆 ...
- HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)
HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意: 给一个序列由 ...
- HDU 1394 Minimum Inversion Number ( 树状数组求逆序数 )
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number ...
- HDU 1394 Minimum Inversion Number(线段树/树状数组求逆序数)
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- HDU 1394 Minimum Inversion Number(最小逆序数 线段树)
Minimum Inversion Number [题目链接]Minimum Inversion Number [题目类型]最小逆序数 线段树 &题意: 求一个数列经过n次变换得到的数列其中的 ...
随机推荐
- SIP学习之网络链接
风清扬的CSDN博客 文章分类SIP http://blog.csdn.net/ppy521/article/category/1227390
- POJ 3378
题目链接 查找长度为5的上升序列总数 用的树状数组+高精度 用树状数组求在i前面比i小的数有几个 用的4个树状数组,A[i][j]表示长度为i的以j为结尾的个数,A[i][j]=A[i-1][1... ...
- easyui获取日期datebox中的值
<input type="text" class="easyui-datebox" id="CTIME" style="wi ...
- dbda封装类(包括:返回二维数组、Ajax调用返回字符串、Ajax调用返回JSON)
<?php class DBDA { public $host = "localhost"; public $uid = "root"; public $ ...
- python数据类型—列表(增改删查,统计,取值,排序)
列表是最常用的数据类型之一,通过列表可以对数据实现方便的存储,修改等操作. 先声明一个空列表: >>> names = [] >>> names [] 可以存多个值 ...
- hibernate错题解析
01 Hibernate错题分析 解析: 此题目考查的是对Hibernate中交叉连接的理解.HQL支持SQL风格的交叉连接查询,交叉连接适用于两个类之间没有定义任何关联时.在where字句中,通 ...
- 自己意淫的一个简陋的Python网站扫描器
使用的模块 threading.optparse.urllib2 本地需要放字典,名字需大写. 上代码 def request(url,pathName): try: import urllib2 p ...
- iphone开发之适配iphone5
iphone5出来了,从不用适配的我们也要像android一样适配不同分辨率的屏幕了. 公司产品新版本需要适配iphone5,经过一番折腾算是搞定了.下面分享给大家: iphone5的屏幕分辨 ...
- 高效求幂取余 算法,复杂度 log(n)
做TopCoder SRM 576 D2 L3 题目时,程序有个地方需要对一个数大量求幂并取余,导致程序运行时间很长,看了Editoral之后,发现一个超级高效的求幂并取余的算法,之前做System ...
- C++关键字之const
C++的const关键字一直让我很乱,这里把const关键字在程序中常用的三个地方分别总结出来: 1. 通过指针或引用访问普通变量 2. 通过对象调用成员函数,通过成员函数访问成员变量 3. 通 ...