题面

luogu

bzoj

题目大意:

  • 给你一个长度为\(n\)的序列,元素都在\(1-k\)之间,有些是\(-1\),让你把\(-1\)也变成\(1-k\)之间的数,使得逆序对最多,求逆序对最少是多少

  • \(n<=10000,k<=100\)

题解

结论:

填的数是不下降的

证明:

假设相邻的两个-1的位置是(x,y)(a[x]<=a[y]);
如果交换x,y;
对1-x和y-n中的数显然没有影响.
对x-y中大于max(a[x],a[y])和小于min(a[x],a[y])的数显然也没有影响.
但是对x-y中a[x]-a[y]的数,逆序对数显然增加了.
所以交换x,y只会导致逆序对数不降.
所以-1位置的数一定是单调不降的.

\(l[i][j]\)表示前\(i\)个数有多少大于\(j\)的数

\(r[i][j]\)表示后\(i\)个数有多少小于\(j\)的数

我们把-1位置弄出来\(dp\)

\(f[i][j]\)表示第\(i\)位填\(j\),逆序对个数最少是多少

\(b[i]\)表示第i个空在原序列的位置

假设\(i\)位填\(t\)

\(f[i][t] = min(f[i-1][z]+l[b[i]][t]+r[b[i]][t])\)

这样复杂度是\(O(n*k^2)\)

  • 注意还要加上没填数时的逆序对

可以发现\(f[i-1][z]\) 可以用一个前缀最小来优化

Code

#include<bits/stdc++.h>

#define LL long long
#define RG register using namespace std;
template<class T> inline void read(T &x) {
x = 0; RG char c = getchar(); bool f = 0;
while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
x = f ? -x : x;
return ;
}
template<class T> inline void write(T x) {
if (!x) {putchar(48);return ;}
if (x < 0) x = -x, putchar('-');
int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}
const int N= 10010;
int cnt, l[N][110], r[N][110], a[N], b[N];
LL f[N][110], g[N][110];
int main() {
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
int n, k; read(n); read(k);
for (int i = 1; i <= n; i++) {
read(a[i]);
if (a[i] == -1) b[++cnt] = i;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= k; j++) {
l[i][j] = l[i-1][j];
if (a[i] > j) l[i][j]++;
}
for (int i = n; i >= 1; i--)
for (int j = 1; j <= k; j++) {
r[i][j] = r[i+1][j];
if (a[i] < j && a[i] != -1) r[i][j]++;
}
for (int i = 1; i <= cnt; i++) g[i][0] = 1ll << 60;
for (int i = 1; i <= cnt; i++)
for (int j = 1; j <= k; j++) {
f[i][j] = g[i-1][j]+l[b[i]][j]+r[b[i]][j];
g[i][j] = min(g[i][j-1], f[i][j]);
}
LL ans = 1ll << 60;
for (int i = 1; i <= k; i++) ans = min(ans, f[cnt][i]);
for (int i = 1; i <= n; i++) ans += l[i][a[i]];
printf("%lld\n", ans);
return 0;
}

洛谷 P4280 bzoj1786 [AHOI2008]逆序对(dp)的更多相关文章

  1. bzoj1831: [AHOI2008]逆序对(DP+双精bzoj1786)

    1831: [AHOI2008]逆序对 Description 小可可和小卡卡想到Y岛上旅游,但是他们不知道Y岛有多远.好在,他们找到一本古老的书,上面是这样说的: 下面是N个正整数,每个都在1~K之 ...

  2. 【洛谷 P2513】 [HAOI2009]逆序对数列(DP)

    题目链接 这种求方案数的题一般都是\(dp\)吧. 注意到范围里\(k\)和\(n\)的范围一样大,\(k\)是完全可以更大的,到\(n\)的平方级别,所以这暗示了我们要把\(k\)写到状态里. \( ...

  3. 洛谷 P1393 P3157 动态逆序对

    嘛,好久没碰CDQ分治了,做道题练练手. 时间倒流——把删数改为加数. 对于每个被删的,我的想法是拆成询问和add,后来发现一个足矣. 我本来准备对每个删的数都求一遍整体逆序对,后来发现无论如何都不可 ...

  4. 洛谷 P3157 [CQOI2011]动态逆序对 解题报告

    P3157 [CQOI2011]动态逆序对 题目描述 对于序列\(A\),它的逆序对数定义为满足\(i<j\),且\(A_i>A_j\)的数对\((i,j)\)的个数.给\(1\)到\(n ...

  5. 洛谷 P3157 [CQOI2011]动态逆序对(树套树)

    题面 luogu 题解 树套树(树状数组套动态开点线段树) 静态使用树状数组求逆序对就不多说了 用线段树代替树状数组,外面套树状数组统计每个点逆序对数量 设 \(t1[i]\)为\(i\)前面有多少个 ...

  6. 洛谷P1966 火柴排队(逆序对)

    题意 题目链接 Sol 不算很难的一道题 首先要保证权值最小,不难想到一种贪心策略,即把两个序列中rank相同的数放到同一个位置 证明也比较trivial.假设\(A\)中有两个元素\(a, b\), ...

  7. 洛谷 P3157 [CQOI2011]动态逆序对 | CDQ分治

    题目:https://www.luogu.org/problemnew/show/3157 题解: 1.对于静态的逆序对可以用树状数组做 2.我们为了方便可以把删除当成增加,可以化动为静 3.找到三维 ...

  8. 洛谷【P1908】逆序对

    题目传送门:https://www.luogu.org/problemnew/show/P1908 所谓逆序对,就是序列中\(a[i]>a[j]\)且\(i<j\)的有序对. 所以我们在归 ...

  9. 洛谷P3157 [CQOI2011]动态逆序对

    题目大意: 给定\(1\)到\(n\)的一个排列,按照给定顺序依次删除\(m\)个元素,计算每个元素删除之前整个序列的逆序对数量 基本套路:删边变加边 那么我们不就是求满足\(pos_i<pos ...

随机推荐

  1. laravel 队列

    php artisan  queue:table 先创建job 队列表 php artisan migrate 执行表 php artisan make:job SendMessage 创建一个job ...

  2. tomcat的配置文件有那些

    配置文件一般都在conf文件夹里,主要有server.xml,context.xml,tomcat_user.xml,web.xml四个常用配置文件,server主要是服务器设置的,例如端口设置,路径 ...

  3. 面试题--CVTE

    2.HashMap和HashSet的实现原理,hashset 和hashMap区别 HashSet底层就是HashMap实现的, *HashMap* *HashSet* HashMap实现了Map接口 ...

  4. xml 操作(动态添加 property属性 其他节点同理)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  5. Python 函数习题

    #encoding=utf-8 from urllib.request import urlopen import random import os ''' 1. 定义一个fuc(url, folde ...

  6. PopupWindow简单使用(一)

    1.构造函数 //方法一:     public PopupWindow (Context context)     //方法二:     public PopupWindow(View conten ...

  7. C#多线程编程实战1.2暂停线程(休眠)

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  8. Kotlin 函数和函数表达式

    学习了kotlin 的控制. 其中最为强大的是各种控制可以直接作为表达式来使用. 那么在kotlin中,函数也是可以作为表达式来使用. 而且kotlin中函数的创建方式有很多方式. 第一种: 传统创建 ...

  9. 关于小程序bindregionchange事件在IOS崩溃的问题

    先说下原因,我在bindregionchange事件触发函数中设置了经纬度,而latitude和longitude是绑定在map组件上的,滑动地图的过程中重新设置了地图中心点的经纬度,会导致地图本身的 ...

  10. ubuntu14.10,解决按照最新版Gnome 15.10后,经典Gnome桌面字体问题!

    ubuntu14.10刚安装完毕,我首先按照了经典Gnome桌面,随后我发现ubuntu软件中心里面能找到的软件明显不如先前我安装过的ubuntu了,我觉得有可能是因为我以前安装的ubuntu14.1 ...