BZOJ3427 Poi2013 Bytecomputer

来源:互联网 发布:js new是什么意思 编辑:程序博客网 时间:2024/03/29 21:21

发现答案肯定是前边一段-1,中间一段0,后边一段1的形式(可能有的段长度为0),可以证明出现2或者-2或者绝对值更大的数一定不是最优解

做一个f[i]和g[i],f[i]表示把i到n都变成1的代价,g[i]表示把1到i都变成-1的代价

那么如果第一个数就是1,那么肯定要把所有数都变成1,如果第一个数是0,那么我们找到第一个不是0的数,如果这个数是1,那么答案就是前边都是原来的0,把后边的数都变成1,如果这个数是-1,那么就无解了(也只有这种情况是无解的)

考虑第一个数是-1,那么如果不存在0那一段的话,我们枚举所有的1的位置作为第一个1,f[i]+g[i-1]更新答案即可,考虑如果有一段得0,那么要么最后没有得1的段,要么这段0后边的数原来就是1。且这段0除了第一个0以外肯定原来就都是0,第一个0原来可能是0也可能是是1,所以枚举原串里所有的极长全0子串[l,r]满足a[r+1]=1或r=n,若a[l-1]==-1,用g[l-1]+f[r+1]更新答案,否则用g[l-2]+1+f[r+1]更新答案

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<vector>#include<map>#include<set>#include<bitset>#include<queue>#include<stack>using namespace std;#define MAXN 1000010#define MAXM 1010#define INF 1000000000#define MOD 1000000007#define eps 1e-8#define ll long longint n;int a[MAXN];int f[MAXN],g[MAXN];int ans=INF;int main(){int i;scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&a[i]); }for(i=n;i;i--){f[i]=f[i+1]+1-a[i];}bool flag=1;for(i=1;i<=n;i++){if(a[i]==1){flag=1;}if(!flag){f[i]=INF;}}if(a[1]==1){printf("%d\n",f[1]);return 0;}if(a[1]==0){for(i=1;a[i]==0&&i<=n;i++){}if(a[i]==-1){printf("BRAK\n");}else{printf("%d\n",f[i]);}return 0;}for(i=1;i<=n;i++){g[i]=g[i-1]+a[i]+1;}int lst;ans=g[n];for(i=1;i<=n;i++){if(a[i]==1){ans=min(ans,f[i]+g[i-1]);}}for(i=n;i;i--){if(a[i]==0&&(a[i+1]==1||i==n)){lst=i+1;while(!a[i]){i--;}if(a[i]==1){ans=min(ans,f[lst]+g[i-1]+1);}else{ans=min(ans,f[lst]+g[i]);}}}printf("%d\n",ans);return 0;}/**/


0 0
原创粉丝点击