比赛时候弄错了一行代码,一直没AC,吐血。。。
直接贪心,从后往前翻,只要出现连续两个1就进行翻转,这样就能确保收益大于直接修改的,具体细节看代码(不过好像dp的方法比较无脑,贪心的细节容易错,好吧,还是太菜了)
记录修改的位置,通过二分查找判断每个点在翻转完毕以后是1还是0,如果是1就需要修改。
#include <bits/stdc++.h>
using namespace std;
int a[100100],pre[100100];
int loc[100100];
int lian0[100100],lian1[100100];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==0)
{
if(a[i-1]!=0) lian0[i]=1;
else lian0[i]=lian0[i-1]+1;
lian1[i]=0;
}
else if(a[i]==1)
{
if(a[i-1]!=1) lian1[i]=1;
else lian1[i]=lian1[i-1]+1;
lian0[i]=0;
}
}
//for(int i=1;i<=n;i++) cout<<lian0[i]<<" "<<lian1[i]<<endl;
bool flag=true;
int cnt=0;
int top=0;
for(int i=n;i>=1;i--)
{
if(flag&&lian1[i]>1&&a[i]==1)//翻转
{
loc[top++]=i;
cnt++;
flag=false;
}
else if(flag==false&&lian0[i]>1&&a[i]==0)//翻转
{
loc[top++]=i;
cnt++;
flag=true;
}
}
reverse(loc,loc+top);
//for(int i=0;i<top;i++) cout<<loc[i]<<" ";
for(int i=1;i<=n;i++)
{
int p=lower_bound(loc, loc+top, i)-loc;
p=top-p;
//cout<<i<<"-p:"<<p<<endl;
if((p&1)==1&&a[i]==0)
{
cnt++;
//cout<<"i:"<<i<<endl;
}
else if((p&1)==0&&a[i]==1)
{
cnt++;
//cout<<"i:"<<i<<endl;
}
}
printf("%d\n",cnt);
}


京公网安备 11010502036488号