题目:
简述:一个01序列,已知某些位置为1,其他未知,要求任意连续的k个数中最多只有k/2个1(k为一个定值),求序列中最多有多少个1
Garth likes apples and oranges. Recently he bought N fruits, where each fruit was either an apple or an orange. Then he ate all N fruits in some order. You are given an int K. Garth observed that at every point in time, if he made a list of the last K fruits he ate, there were at most K/2 (rounded down) apples in this list. For each valid i, you know that the info[i]-th fruit Garth ate was an apple. (Fruits Garth ate are numbered starting from 1. For example, info[i]=1 means that the very first fruit Garth ate was an apple.) Please find and return the maximum number of apples Garth could have eaten. |
思路:如果所有位置都是未知,那么显然可以把序列每k个分成1段,将第一段放k/2个1,然后复制N/k次可以构造出一个满足条件的序列。另外为了使1最多,我们希望剩下的n%k个数中有尽量多的1,所以第一段的前k/2个数都放1,后面的都放0。现在需要处理某些位置已经是1,而在构造序列中是0的情况。解决的思路是“1换1”,将前k-1个位置中的1变为0,将这一位变为1.需要注意的是和当前位置在同一个k区间的1位置是不允许变为0的。另外如果1边0的位置在上一段中,需要将最后的结果-1
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
class ApplesAndOrangesHard{
public:
int a[100005];
int maximumApples(int n,int k,vector<int> info){
int i,j;
memset(a,0,sizeof(a));
for(i=0;i<(k/2);i++){
a[i]=1;
}
int ans=n/k*(k/2);
for(i=0;i<info.size();i++){
int id=info[i]/k+2,pos=info[i]%k;
if(!a[pos]){
for(j=0;j<k;j++){
int x=(pos-j-1+k)%k;
if(!a[x]) continue;
if(x<pos&&a[x]==id) continue;
if(x>pos&&a[x]>=id-1) continue;
a[x]=0;
if(x>pos) ans--;
break;
}
}
a[pos]=id;
}
for(i=0;i<n%k;i++){
if(a[i]) ans++;
}
return ans;
}
};
int main(){
int n,k,m;
vector<int> a;
while(scanf("%d%d%d",&n,&k,&m)!=EOF){
a.clear();
for(int i=1;i<=m;i++){
int x;
scanf("%d",&x);
a.push_back(x);
}
ApplesAndOrangesHard t;
cout<<t.maximumApples(n,k,a)<<endl;
}
return 0;
}