bzoj1831【AHOI2008】逆序对

1831: [AHOI2008]逆序对

Time Limit: 10 Sec  Memory Limit: 64 MB

Submit: 485  Solved: 341

[Submit][Status][Discuss]

Description

小可可和小卡卡想到Y岛上旅游,但是他们不知道Y岛有多远。好在,他们找到一本古老的书,上面是这样说的: 下面是N个正整数,每个都在1~K之间。如果有两个数A和B,A在B左边且A大于B,我们就称这两个数为一个“逆序对”。你数一数下面的数字里有多少个逆序对,你就知道Y岛离这里的距离是多少千米了。 比如说,4 2 1 3 3里面包含了5个逆序对:(4, 2), (4, 1), (4, 3), (4, 3), (2, 1)。 可惜的是,由于年代久远,这些数字里有一部分已经模糊不清了,为了方便记录,小可可用“-1”表示它们。比如说,4
2 -1 -1 3 可能原来是4 2 1 3 3,也可能是4 2 4 4 3,也可能是别的样子。 小可可希望知道,根据他们看清楚的这部分数字,能不能推断出这些数字里最少能有多少个逆序对。

Input

第一行两个正整数N和K。第二行N个整数,每个都是-1或是一个在1~K之间的数。

Output

一个正整数,即这些数字里最少的逆序对个数。

Sample Input

5 4

4 2 -1 -1 3

Sample Output

4

HINT

4 2 4 4 3中有4个逆序对。当然,也存在其它方案得到4个逆序对。

数据范围:

100%的数据中,N<=10000,K<=100。

60%的数据中,N<=100。

40%的数据中,-1出现不超过两次。

Source

Day1

动态规划

首先,我们考虑填入的数需要满足的性质。

对于两个空位a和b,分别填入数x和y,且x<y。

如果我们交换x和y,会有如下性质:

1.[1,a-1]和[b+1,n]中的数与x y构成的逆序对数不变。

2.[a+1,b-1]中大于x或小于y的数与x y构成的逆序对数不变。

3.[a+1,b-1]中在(x,y)范围内的数与x y构成逆序对。

4.x y构成逆序对。

也就是说我们如果交换x y,逆序对数会增加。

所以填入的这些数一定是单调不减的。

有了这个性质我们就可以DP了。

用f[i][j]表示第i个空位填j所形成的最小逆序对,g[i][j]表示f[i][1]-f[i][j]的最小值,cost[i][j]表示在第i个空位填j所形成的新的逆序对。显然cost[i][j]是可以预处理的。

则f[i][j]=g[i-1][j]+cost[i][j]。

注意最终答案还要加上不是空位的数形成的逆序对数。

(感觉自己表达能力好差......看不懂的话还是看代码吧...QAQ)

时间: 2024-12-28 00:16:35

bzoj1831【AHOI2008】逆序对的相关文章

BZOJ1831: [AHOI2008]逆序对

1831: [AHOI2008]逆序对 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 341  Solved: 226[Submit][Status] Description 小可可和小卡卡想到Y岛上旅游,但是他们不知道Y岛有多远.好在,他们找到一本古老的书,上面是这样说的: 下面是N个正整数,每个都在1~K之间.如果有两个数A和B,A在B左边且A大于B,我们就称这两个数为一个“逆序对”.你数一数下面的数字里有多少个逆序对,你就知道Y岛离这里的距离

动态规划 BZOJ1831 [AHOI2008]逆序对

1831: [AHOI2008]逆序对 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 660  Solved: 469[Submit][Status][Discuss] Description 小可可和小卡卡想到Y岛上旅游,但是他们不知道Y岛有多远.好在,他们找到一本古老的书,上面是这样说的: 下面是N个正整数,每个都在1~K之间.如果有两个数A和B,A在B左边且A大于B,我们就称这两个数为一个"逆序对".你数一数下面的数字里有多少个逆序

BZOJ1786: [Ahoi2008]Pair 配对/1831: [AHOI2008]逆序对

这两道题是一样的. 可以发现,-1变成的数是单调不降. 记录下原有的逆序对个数. 预处理出每个点取每个值所产生的逆序对个数,然后dp转移. #include<cstring> #include<iostream> #include<cstdio> #include<map> #include<cmath> #include<algorithm> #define rep(i,l,r) for (int i=l;i<=r;i++)

bzoj1786: [Ahoi2008]Pair 配对&amp;&amp;1831: [AHOI2008]逆序对

一个自以为很对的东西,我们往-1放的数肯定是不增的. 然后就预处理一下,假如i这个位置放j会多多少逆序对. DP一下,我的复杂度应该是O(n*m^2)的,然而你随便搞都能省掉一个m吧,我算了算好像可以过就不管了. 注意树状数组的时候getsum是a[i]-1,相同是不算逆序对的 #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorit

[AHOI2008] 逆序对

link 我们可以很容易的推断出$-1$是单调不降的,若$i>j$且$a_i$与$a_j$都没有填数,若填完之后$a_i>a_j$或者$a_i<a_j$,则对答案产生影响的只在$[i,j]$之间,则$a_i<a_j$对答案产生的贡献更小,则其实每个不同位置的$-1$其实是互不影响的,所以就可以用$dp$实现 设$dp(i,j)$表示这是从右往左数第$i$个$-1$,这里填j的最小逆序对数(这里的逆序对是只与$-1$有关的,其他的单算) 则$dp(i,j)=min(dp(i-1,p)

P4280 [AHOI2008]逆序对

传送门 有一个不会证明的贪心:从左到右考虑每一个位置,然后在每一个位置都贪心选取能让该位置构成的逆序对最少的数.判断逆序对的话只要记一下前缀小于等于某数的总数和后缀小于等于某数的总数就行了 //minamoto #include<bits/stdc++.h> #define rint register int #define inf 0x3f3f3f3f #define ll long long using namespace std; #define getc() (p1==p2&&

【[AHOI2008]逆序对】

被锤爆了 被这个题搞得自闭了一上午,觉得自己没什么前途了 我又没有看出来这个题的一个非常重要的性质 我们填进去的数一定是单调不降的 首先如果填进去的数并不是单调不降的,那么填进去本身就会产生一些逆序对,感性理解好像是单调不降更优,这里还是严谨证明一下吧 考虑一下树状数组求逆序对的过程,显然就是求出每一个数前面有多少个比它大的数 这张图好丑啊 设\(A<B\),\(x\)表示那段绿色区间里大于\(A\)的数,\(y\)表示绿色区间里大于\(B\)的数,\(a\)表示蓝色区间里大于\(A\)的数,\

[BZOJ1786][BZOJ1831]逆序对

试题描述 输入 输出 输入示例 5 4 4 2 -1 -1 3 输出示例 4 数据规模及约定 见“输入” 题解 首先这题有一个性质,即,填的数从左到右一定不降.证明不妨读者自己yy(提示:用先按降序填,交换后答案一定不会更差的思想证). 那么新添的数字一定不会造出逆序对了. 然后设计 dp,设 f(i, j) 表示考虑前 i 个打“-1”的位置,最后一个(第 i 个)位置填写数字 j 时,与已经固定的数字产生最少的逆序对数. 有 f(i, j) = min{ f(i-1, x) | 0 < x 

BZOJ1786 [Ahoi2008]Pair 配对 动态规划 逆序对

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1786 题意概括 给出长度为n的数列,只会出现1~k这些正整数.现在有些数写成了-1,这些-1可以变成任何数. 求把这些-1变成1~k中的正整数之后,最少的逆序对个数为多少. 题解 我们可以判断,这些-1中写的数字一定是单调不降的. 为什么?我们把答案序列的所有-1位抽出来,如果答案序列中有一组是逆序的,那么交换他们,一定可以保证小的那个换到大的那个的位置的时候,它左右产生的逆序对数一定比大的原先