The inversion number of a given number sequence a1, a2, …, an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.

For a given sequence of numbers a1, a2, …, an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:

a1, a2, …, an-1, an (where m = 0 - the initial seqence)
a2, a3, …, an, a1 (where m = 1)
a3, a4, …, an, a1, a2 (where m = 2)

an, a1, a2, …, an-1 (where m = n-1)

You are asked to write a program to find the minimum inversion number out of the above sequences.
Input
The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.
Output
For each case, output the minimum inversion number on a single line.
Sample Input
10
1 3 6 9 0 8 5 7 4 2
Sample Output
16

挺恼火的一个题,wa了好几次,还是不能很好地理解权值线段树的一些比较深奥的东西。
题意就是不断的把第一个元素放到最后一个位置上所形成的逆序对的个数,最少是多少。。
我们先求出初始序列的逆序对数。
在不断的把起始元素放到最后一个位置上时,逆序对的改变是n-a[i]-a[i]-1。希望有大佬能告诉我这原理是什么,不明白到底为什么是酱紫。求逆序対用了两种方式权值线段树和树状数组。树状数组更快一点、
代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;const int maxx=5e3+100;
struct node{int l;int r;int v;
}p[maxx<<2];
int a[maxx],b[maxx];
int n;void pushup(int cur)
{p[cur].v=p[cur<<1].v+p[cur<<1|1].v;
}
void build(int l,int r,int cur)
{p[cur].l=l;p[cur].r=r;p[cur].v=0;if(l==r) return ;int mid=l+r>>1;build(l,mid,cur<<1);build(mid+1,r,cur<<1|1);pushup(cur);
}
void update(int pos,int cur,int add)
{int L=p[cur].l;int R=p[cur].r;if(L==R){p[cur].v=1;return ;}int mid=L+R>>1;if(pos<=mid) update(pos,cur<<1,add);else update(pos,cur<<1|1,add);pushup(cur);
}
int query(int cur,int l,int r)
{int L=p[cur].l;int R=p[cur].r;if(l<=L&&R<=r) return p[cur].v;int mid=L+R>>1;if(r<=mid) return query(cur<<1,l,r);else if(l>mid) return query(cur<<1|1,l,r);else return query(cur<<1,l,mid)+query(cur<<1|1,mid+1,r);
}
int main()
{while(scanf("%d",&n)!=EOF){build(1,n,1);for(int i=1;i<=n;i++) scanf("%d",&a[i]);int ans=0;for(int i=1;i<=n;i++){b[i]=a[i]+1-query(1,1,a[i]+1)-1;ans+=b[i];update(a[i]+1,1,1);}int sum=ans;for(int i=1;i<=n;i++){sum+=n-a[i]-(a[i]+1);//!!!记住规律!!! ans=min(ans,sum);}printf("%d\n",ans);}
}//11 2 4 5 8 1 6 3 10 9 11 7

树状数组

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;const int maxx=5e3+100;
int b[maxx],c[maxx];
struct node{int id;int v;
}p[maxx];
int n;
bool cmp(const node &a,const node &b)
{return a.v<b.v;
}
bool cmp1(const node &a,const node &b)
{return a.id<b.id;
}
int lowbit(int x){return x&-x;}
void update(int cur)
{while(cur<=2*n){c[cur]+=1;cur+=lowbit(cur);}
}
int query(int cur)
{int ans=0;while(cur){ans+=c[cur];cur-=lowbit(cur);}return ans;
}
int main()
{while(scanf("%d",&n)!=EOF){memset(c,0,sizeof(c));for(int i=1;i<=n;i++) scanf("%d",&p[i].v),p[i].id=i;sort(p+1,p+1+n,cmp);int ans=0;for(int i=1;i<=n;i++){b[i]=(i-query(p[i].id)-1);ans+=b[i];update(p[i].id);}int sum=ans;sort(p+1,p+1+n,cmp1);for(int i=1;i<n;i++){sum+=n-p[i].v-p[i].v-1;ans=min(ans,sum);}printf("%d\n",ans);}return 0;
}

努力加油a啊,(o)/~

Minimum Inversion Number HDU - 1394(权值线段树/树状数组)相关推荐

  1. Minimum Inversion Number HDU - 1394(求一个数字环的逆序对+多种解法)

    题意: 给出n个数(0~n-1,每个数仅出现一次),问它长为n的循环序列中逆序对最少的数量. 多种解法:暴力+树状数组+分治+规律推导公式 题目: The inversion number of a ...

  2. HDOJ1394 Minimum Inversion Number【线段树】

    需要注意的就是给出的数是0~n-1,而线段树根节点范围是1-n 所以main中insert要num[i]+1. 当然,根节点范围换成0~n-1就不需要了. Problem : 1394 ( Minim ...

  3. 权值线段树小结(hdu多校,普通平衡树,郁闷的出纳员)

    之前刷了一点主席树的题目,但是没有系统的做过权值线段树的题目.主席树是多根权值线段树的综合.权值线段树可以解决在总区间里求第k大的问题.在普通的线段树里,我们每一个节点维护的是权值大小.但是在权值线段 ...

  4. 逆序数2 HDOJ 1394 Minimum Inversion Number

    题目传送门 1 /* 2 求逆序数的四种方法 3 */ 1 /* 2 1. O(n^2) 暴力+递推 法:如果求出第一种情况的逆序列,其他的可以通过递推来搞出来,一开始是t[1],t[2],t[3]. ...

  5. 【HDU - 5489】Removed Interval(离散化,权值线段树,思维,最长上升子序列)

    题干: Given a sequence of numbers A=a1,a2,-,aNA=a1,a2,-,aN, a subsequence b1,b2,-,bkb1,b2,-,bk of AA i ...

  6. Minimum Inversion Number 线段树

    The inversion number of a given number sequence a1, a2, -, an is the number of pairs (ai, aj) that s ...

  7. 2019CCPC网络赛 1002 HDU 6703(权值线段树)

    2019CCPC网络赛 1002 HDU 6703(权值线段树) 思路:用权值线段树存题目给的数据后,2操作就是求权值线段树中大于等于k的部分中,靠近左端点的第一个大于r的值(这个求出来的只是原序列中 ...

  8. [HDU1394]Minimum Inversion Number

    题目:Minimum Inversion Number 链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 分析: 1)先对序列求逆序对的数目,归并排序 ...

  9. Governing sand(权值线段树/主席树)

    链接:https://ac.nowcoder.com/acm/contest/887/C 来源:牛客网 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 65536K,其他语言13107 ...

最新文章

  1. Android网络框架-OkHttp3.0总结
  2. java聊天室 博客_java网络聊天室
  3. 如何制定恰当的信息安全策略
  4. 互联网协议 — QUIC 快速 UDP 互联网连接
  5. Linux防火墙命令
  6. 今日浅谈循环 for与while
  7. Spring注解之@Transactional对于事务异常的处理
  8. WinXP下 扫雷程序逆向分析 --扫雷辅助(一)
  9. ajax alert表单,jQuery AJAX Post alert()不被调用
  10. 管理后台--1.创建分类
  11. jQuery 前后端分离项目总结
  12. 计算器c语言源代码全,C语言的计算器源代码
  13. 利用css做导航栏,利用CSS制作导航栏
  14. ADF单位根检验三种形式_【EViews】面板数据的处理方法及检验步骤
  15. props传值强校验validator
  16. 基于SVG的绘制多边形jQuery插件
  17. pythonend输出最后没有逗号_python不换行之end=与逗号的意思及用途
  18. PREMIS元数据字典3.0阅读笔记(一)
  19. 图像分割-分水岭算法和GrabCut 算法
  20. 什么才算是关键指标?如何选择关键指标? by彭文华

热门文章

  1. swift5自定义构造函数和自定义变量报required init?(coder: NSCoder) { fatalError(“init(coder:) has not bee错问题
  2. IOS之截取特定字符串
  3. android webview参数,Android webView解析URL参数
  4. 笔记本电脑有蓝牙连接功能吗_超 Cool 的冷藏箱品牌与PRO TREK PRT-B70你见到过吗?...
  5. MailCore2 SDK API
  6. iPhone/iOS图片相关(读取、保存、绘制、其它相关)
  7. nfs linux系统服务,Linux系统服务搭建之NFS
  8. TF从文件中读取数据
  9. 尚洋优选健康美电商平台启动仪式在广州召开
  10. Securing Spring Cloud Microservices With OAuth2