[COCI2017-2018#5] Karte,简短的代码想到了就AC
这道题是SPJ放心搞
但是我的脑子里面的东西,不用我多说,你们就知道是水和面粉和成的
看招 题
【题目描述】
你有一副共有N张牌的牌,在第i张牌上会有一个数字ai表示在这张牌下面至少一共有ai张牌上的信息是假的。接下来你需要对这副牌进行洗牌,使得这副牌当中,恰好有K张牌的信息是错误的。
【输入输出格式】
第一行输入两个数字N、K(1≤N≤5105,0≤K≤N)。
接下来N行,每行输入一个数字,表示第i张牌上的数字ai(0≤ai≤5105)
如果不存在恰好K张牌上的信息是错误的情况,则输出-1,否则,将这副牌从上往下输出这N张牌上的所对应的ai。如果有多种答案,输出任意一种。
【样例】
样例输入1
4 2
1
2
2
3
样例输出1
2 3 1 2
样例输入2
5 3
2
1
3
0
3
样例输出2
3 3 0 1 2
样例输入3
6 4
0
2
5
2
0
1
样例输出3
-1
【样例分析】
对于样例2:第5张牌后没有牌,所以他后面是错误的牌的数量应该是0,但他是2,所以这张牌是错误的。第4牌后面有1张牌是错误的(第5张),它上面写的是1,所以是正确的。第3张牌上写的是0,它后面有1张牌是错误的(第5张),所以它是正确的(题目说的是至少有,不是确定有)。第2张牌上面写的是3,但它后面只有一张是错误的(第5张)所以是错误的。第1张牌上写的是3,但它后面只有2张是错误的(第2张和第5张),所以是错误的。即一共有3张是错误的。
【正解】
把a数组进行从小到大sort然后把n-k+1到n的值逆序倒过来存储
再用一个for循环从后往前判断错误信息个数最后按照题意输出就行了
完啦!这道题就可以AC了
但是作为一个有良心的大大!
我必须证明威慑么!!
1)如果错误信息个数<k,因为只有在ai越大而i又越靠前的时候ai才更大几率的错,我们按照最大几率去排序,个数都不够,那么其他方案一样也不够
2)如果错误信息个数>k,就意味着n-k+1到n之间一定所有都是错误的信息,假设在n-k+1到n之间有一个i的信息是正确的,而1到n-k中每一个aj值都小于ai,那么它们的信息也一定是正确的,个数就不可能大于k,故假设不成立。那么如果我们交换i,j是否会减少k呢?过来人告诉不会,k只可能不变或者+1.因为如果我们换了i,j,j本身就是正确的,换过来了有可能也是正确,甚至是错误的导致k+1,而i换过去了前面错误的个数也不会变,就算j导致k+1使得i正确的话,k再-1也是不变,所以不管怎样都不会使得k最少
好了,话不多说,屁不多放,上马
【代码实现】
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAXN 500005
int n, k;
int a[MAXN], b[MAXN];
int main() {scanf ( "%d %d", &n, &k );for ( int i = 1;i <= n;i ++ )scanf ( "%d", &a[i] );sort ( a + 1, a + n + 1 );int cnt = 0;for ( int i = 1;i <= n - k;i ++ )b[++ cnt] = a[i];for ( int i = n;i >= n - k + 1;i -- )b[++ cnt] = a[i];cnt = 0;for ( int i = n;i >= 1;i -- )if ( b[i] > cnt ) cnt ++;if ( cnt == k )for ( int i = 1;i <= n;i ++ )printf ( "%d\n", b[i] );else printf ( "-1" );return 0;
}
平A小王子,AWM一枪爆掉你的三级头
不懂的地方,欢迎各位xjj,xgg留言,bye~~