比赛时候弄错了一行代码,一直没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); }