题意

给定一个长度为\(n\),值域为\([1,k]\),某些位置不确定的数组,求最小的逆序对。\(n\leq 10^4, k \leq 100\)

题解

这题有人用前缀和优化\(dp\)过了,但是这里还是讲一种逐一填的做法

首先证明:填进去的数一定是单调不减的,换句话说不构成逆序对。证明很简单,因为假设在\(i\),\(j\)两处(\(i < j\)),填进去的数构成逆序对,交换这\(i, j\),不影响\([1, i - 1],[j + 1, n]\)的逆序对,对于\([i + 1, j - 1]\)来说逆序对减少或不变,并且\(i,j\)构成的逆序对消失。

所以我们只要考虑已经填好的数。每次找到一个贡献最小的\(k\)填就行了。

我用树状数组维护了一下,实际上直接数组也可以。

#include <algorithm>
#include <cstdio>
using namespace std; const int N = 1e4 + 10; int n, k, a[N], bit[2][N]; void add(int z, int x, int y) {
for(; x <= k; x += x & (-x)) bit[z][x] += y;
}
int qry(int z, int x) {
int ans = 0;
for(; x >= 1; x &= x - 1) ans += bit[z][x];
return ans;
} int main() {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i ++) {
scanf("%d", a + i);
if(~ a[i]) add(1, a[i], 1);
}
int ans = 0;
for(int i = 1; i <= n; i ++) {
if(a[i] == -1) {
int x = 1, y = n << 1;
for(int j = 1; j <= k; j ++) {
int s = qry(0, k) - qry(0, j) + qry(1, j - 1);
if(s < y) y = s, x = j;
}
a[i] = x;
add(0, a[i], 1);
} else add(0, a[i], 1), add(1, a[i], -1);
ans += qry(0, k) - qry(0, a[i]);
}
printf("%d\n", ans);
return 0;
}

最新文章

  1. 连载《一个程序猿的生命周期》-《发展篇》 - 3.农民与软件工程师,农业与IT业
  2. 自己常用的webstrom快捷键
  3. fir.im Weekly - 进击的 Swift
  4. sql server 对象资源管理器(一)
  5. 【转】Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案
  6. JSP01
  7. Java 开源分布式缓存框架Ehcache
  8. java web项目中classes文件夹下的class和WEB-INF/lib中jar里的class文件加载顺序
  9. 【HDOJ】5288 OO’s Sequence
  10. winform最小化到托盘
  11. PHP PDO sqlite ,Unable to Open database file的解决方法
  12. 微信公众号开发——通过ffmpeg解决amr文件无法播放问题
  13. installshield安装包制作
  14. python运用PIL制作GIF
  15. jQuery对象和普通DOM对象的区别
  16. 腾讯、爱奇艺、优酷等vip视频在线解析
  17. 用java输入分数,得出分数等级
  18. Go语言字典树定义及实现
  19. mongodb删除重复数据
  20. 761. Special Binary String

热门文章

  1. hihoCoder#1067(离线算法求LCA)
  2. [转载]关于linux下system()函数的总结
  3. Java-API-Package:org.springframwork.transaction.annotation
  4. kafka集群安装和kafka-manager
  5. 关于Java中集合的讲解~
  6. 数据库:ubantu下MySQL数据库备份方法
  7. leetcode874
  8. ListView显示Sqlite的数据
  9. Tornado之抽屉实战(2)--数据库表设计
  10. viewpagerindicator+UnderlinePageIndicator+ viewpage切换