B(2187): 翻轉游戲加強版
阿新 • • 發佈:2018-12-16
B(2187): 翻轉游戲加強版
Submit Page Summary Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 39 Solved: 8
Description
給當一個01串,最多可以對一段區間裡的01取反一次,求最多能取得的1的個數
Input
多組資料,第一行為陣列組數T(T<=10)
每組資料第一行一個整數N,1<=N<=1000000
第二行一個長度為N的01字串
Output
每組資料輸出一行代表答案
Sample Input
2 4 1001 4 1111
Sample Output
4 4
解法:
設f[x]為01串下標1到x中1的個數(我的下標從1開始),d[x]為01串下標1到x中0的個數,假設我翻轉了 l r區間,那麼ans=f[n]-f[r]+f[l-1]+d[r]-d[l-1],f[n]是常數,我們變形一下,答案值和這個有關:f[l-1]-d[l-1]-(f[r]-d[r]),那麼只要這個式子最大,答案才最大,我們令h[x]=f[x]-d[x],只要找到兩個數 l r(l<=r),使得h[l]-h[r]最大即可。
---------------------
作者:一隻叫橘子的貓
來源:CSDN
原文:https://blog.csdn.net/ccsu_cat/article/details/83933795
版權宣告:本文為博主原創文章,轉載請附上博文連結!
下面的註釋是我對這個的解法的理解。
#include<cstdio> #include<algorithm> using namespace std; const int maxn=1e6+10; char s[maxn]; int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d%s",&n,s+1); int p0=0,p1=0,mx=0,t=0,p=0,ans=0;; for(int i=1;i<=n;i++) { ans+=s[i]-'0'; if(s[i]=='0') p0++; else p1++; t=p1-p0; /* 最重要的兩句就是這兩句 數學推論題 */ p=max(p,mx-t); /* p就是答案最大的h(l)-h(r) mx就是儲存最大的h(l) t就是列舉h(r) t=p1-p0即f(x)-d(x) 比較妙的一種數學題吧 */ mx=max(t,mx); } printf("%d\n",ans+p); } }