hdu-1394(线段树&逆序数的性质和求法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394
题目大意:
给出一个序列,一对逆序数就是满足i<j&&a[i]>a[j]条件的一对数字。
每次将a数组的最后一个数放到数组的第一位上,原数组向后移动一位,得到一个新的序列,
求这些序列中最小的逆序数。(每个数都在0-n-1范围内)
求解思路:
(1)逆序数的性质:一个序列第i次循环的逆序数Pi=P(i-1)+(n-1-a[i])-a[i]。
(2)可以通过暴力求解,每次找最小值就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = ;
const int INF = ;
int a[maxn];
int main(void)
{
int mi,cnt,i,j,num,n;
while(~scanf("%d",&n))
{
memset(a,,sizeof(a));
for(i=;i<n;i++) scanf("%d",&a[i]);
mi=INF;cnt=;
for(i=;i<n;i++)
for(j=i+;j<n;j++)
if(a[i]>a[j]) cnt++;
if(mi>cnt) mi=cnt;
for(i=;i<n;i++)
{
cnt=cnt+(n--a[i])-a[i];
if(mi>cnt) mi=cnt;
}
printf("%d\n",mi);
}
return ;
}
(3)线段树做法:
先初始化线段树都为0,然后输入每个数,每个数字+1,即改为1-n区间,判断b[i]+1到n区间内有无数字,有的话逆序数就+1
然后再更新节点b[i]表示这个节点被访问过了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = ;
const int INF = ;
int a[maxn<<],b[maxn];
void pushup(int x)
{
a[x]=a[x*]+a[x*+];
}
void build(int x,int l,int r)
{
if(l==r)
{
a[x]=;return ;
}
int mid=(l+r)/;
build(x*,l,mid);
build(x*+,mid+,r);
pushup(x);
}
void update(int x,int l,int r,int pos)
{
if(l==r)
{
a[x]++;return ;
}
int mid=(l+r)/;
if(pos<=mid) update(x*,l,mid,pos);
if(pos>mid) update(x*+,mid+,r,pos);
pushup(x);
}
int query(int x,int l,int r,int A,int B)
{
if(A<=l&&r<=B) return a[x];
int mid=(l+r)/,ans=;
if(A<=mid) ans+=query(x*,l,mid,A,B);
if(B>mid) ans+=query(x*+,mid+,r,A,B);
return ans;
}
int main(void)
{
int n,i,ans,mi;
while(~scanf("%d",&n))
{
memset(a,,sizeof(a));
memset(b,,sizeof(b));
build(,,n);
ans=;mi=INF;
for(i=;i<=n;i++)
{
scanf("%d",&b[i]);
b[i]++;
ans+=query(,,n,b[i]+,n);
update(,,n,b[i]);
}
if(mi>ans) mi=ans;
for(i=;i<n;i++)
{
ans=ans+(n-b[i]+)-b[i];
if(mi>ans) mi=ans;
}
printf("%d\n",mi);
}
return ;
}
(4)归并排序做法
归并排序时,当a[j]>a[i]时,每次记录tmp+=(mid-i+1),最终求出的tmp就是这个序列的逆序数。
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = ;
int a[maxn],b[maxn],temp[maxn],tmp;
void Merge_Sort(int l,int r,int mid)
{
int pos=,i=l,j=mid+;
while(i<=mid&&j<=r)
{
if(a[i]>a[j]) tmp+=(mid+-i),temp[pos++]=a[j++];
else temp[pos++]=a[i++];
}
while(i<=mid) temp[pos++]=a[i++];
while(j<=r) temp[pos++]=a[j++];
for(i=;i<pos;i++) a[i+l]=temp[i];
}
void Merge(int l,int r)
{
if(l==r) return ;
int mid=(l+r)/;
Merge(l,mid);
Merge(mid+,r);
Merge_Sort(l,r,mid);
}
int main(void)
{
int n,ans,i;
while(~scanf("%d",&n))
{
for(i=;i<n;i++)
{
scanf("%d",&a[i]);b[i]=a[i];
}
tmp=;ans=;
Merge(,n-);
ans=tmp;
for(i=;i<n;i++){
tmp=tmp+n--b[i]*;
if(ans>tmp) ans=tmp;
}
printf("%d\n",ans);
}
return ;
}
hdu-1394(线段树&逆序数的性质和求法)的更多相关文章
- hdu 1394(线段树) 最小逆序数
http://acm.hdu.edu.cn/showproblem.php?pid=1394 给出一列数组,数组里的数都是从0到n-1的,在依次把第一个数放到最后一位的过程中求最小的逆序数 线段树的应 ...
- hdu 1394 (线段树求逆序数)
<题目链接> 题意描述: 给你一个有0--n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,那么每个序列都有一个逆序数,找 ...
- hdu 1394 线段树计算逆序数
线段树计算逆序数的原理: 用线段树来统计已插入的数的个数(所以要保证最大的那个数不能太大,否则数组都开不了),然后每插入一个数,就查询比插入的数大的个数,累加即可. 这个题还有一个特点就是,题目给的是 ...
- HDU 1394 线段树求逆序对
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- HDU 1394 线段树or 树状数组~
Minimum Inversion Number Description The inversion number of a given number sequence a1, a2, ..., an ...
- hdu 1394 线段树
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)
Weak Pair Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total ...
- hdu 3974 线段树 将树弄到区间上
Assign the task Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu 3436 线段树 一顿操作
Queue-jumpers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
随机推荐
- ConcurrentMap与CopyOnWrite容器
ConcurrentMap接口下有两个重要的实现: ConcurrentHashMap ConcurrentSkipListMap(支持并发排序功能,弥补ConcurrentHashMap) Conc ...
- 问题1:canvas绘制图片加载不出来
<head> <script src="js/index.js" type="text/javascript" charset="u ...
- 【python】入门指南1
基础的数据结构:int, float, string 注意:python入门系列的文章的示例均使用python3来完成. #!/bin/python a = 1 b = 1.0 c = 'string ...
- iOS耳机监听
1 .插入耳机的时候并没有切换到耳机播放 仍然是扬声器播放 2 .当一开始手机上已经插入耳机时 ,这时候开启音频播放时 仍然是扬声器播放 因此今天主要谈的就是从这两个问题: 先来解决第一个问题:其实解 ...
- 【Linux 线程】线程同步《一》
1.线程同步概念 线程同步:在多个线程访问共享数据时,有先后次序. 在一般情况下,创建一个线程是不能提高程序的执行效率的,所以要创建多个线程.但是多个线程同时运行的时候可能调用线程函数,在多个线程同时 ...
- 8.17 纯css画一个着重号图标
今天看到一个同事写的着重号图标,我以为是图片,仔细一看,是span标签!哇!!学习一下哈哈 图标长这样: CSS代码: .hint{ display: inline-block; width: 20p ...
- 42-字符串到json 的错误 com.alibaba.fastjson.JSONObject cannot be cast to java.lang.String
json: {"updated_at":1551780617,"attr":{"uptime_h":3,"uptime_m&quo ...
- php7下安装event扩展
有效安排I/O,时间和信号的扩展 使用可用于特定平台的最佳I/O通知机制的事件,是PHP基础设施的libevent端口. 下载地址:http://pecl.php.net/package/event ...
- iOS.UI.UIWindow
UIWindow 1. UIWindow 2. UIWindow的使用场景 2.1 额外添加的Window需要手动进行旋转 最近有遇到一个UIWindow的使用场景:在ApplicationDeleg ...
- CF487E Tourists - Tarjan缩点 + 树剖 + multiset
Solution 先Tarjan求出点双联通分量 并缩点. 用$multiset$维护 点双内的最小点权. 容易发现, 点双内的最小点权必须包括与它相连的割边的点权. 所以我们必须想办法来维护. 所以 ...