题意:你有n个判断题,每题只可能是对或者错的一种,你事先知道了最终答案是对的题目数一定是下列若干种可能的某一个,求如何安排每一道题的选项能在最坏的情况下得到最多的分?
题解:
NOIP模拟赛的题目,被各位大神随便切,我却当场没想出来。
我们把正确答案是对号的题设为1,正确答案是错误的题设为0,这题首先是会发现,直接贪心地全选1或全选0并不一定是最优的,反例是在有8个题,最后可能是1道或7道题是1,那么你全选1或者全选0都是最多对1个,但是如果4个选1,4个选0就至少一定能对4个。
一下部分选自这里,我略作了注释。
首先,我们先提出一个引理:
对于两个长度为
的01串,
中
个1,
中
个1,任一排列中相同位置元素相同的数量至少为
。
接下来我们证明一下。
1、
,即
和
匹配1,
和
中的0全都和1匹配了,考虑匹配了几个1。
我们为了让相同元素尽可能少,考虑把
中的1全移到前端,
中的1全移到后端,变成线段覆盖问题,重合部分为
。
2、
,即
和
匹配0。同理,我们考虑把
中的0全移到前端,
中的0全移到后端,用同样的方法得出该情况下结果为
。
3、
,显然答案为0。
说完了引理,我们再接着讲题。
我们先将
从小到大排序,设当前要匹配的01串为
,其中有
个1。
对于每对
,我们肯定是拿
和
去匹配0,和
去匹配1。
由引理得
。当
时,得
。
同理当
时,得
综上所述,必有
。
于是我们只需要给t排好序之后扫一遍更新ans就行了。
最后还要判断是否全选1或者全选0会更优。
代码:
#include <bits/stdc++.h>
using namespace std;
int n,k,t[1000100],ans;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=k;++i)
scanf("%d",&t[i]);
sort(t+1,t+k+1);
ans=max(t[1],n-t[k]);
for(int i=2;i<=k;++i)
ans=max(ans,(t[i]-t[i-1])/2);
printf("%d\n",ans);
return 0;
}