「日常训练」Alternative Thinking(Codeforces Round #334 Div.2 C)
題意與分析 (CodeForces - 603A)
這題真的做的我頭疼的不得了,各種構造樣例去分析性質。。。
題意是這樣的:給出01字符串。可以在這個字符串中選擇一個起點和一個終點使得這個連續區間內所有的位取反。求經過處理后最多會得到多少次01變換(可以不連續)。
首先求原串的最長01長度,這個太簡單了,然后才是重頭戲:精彩的構造樣例分類討論環節——如何增加01的最長串?
我們考慮一下反轉串的幾種情況:1、反轉單個連續0/1串的內部;2、反轉兩個部分連續0/1串與中間的內容(內部無連續串)3、反轉兩個部分連續0/1串與中間的內容(內部有連續串)4、反轉連續01串(不是0/1串!)
第一種情況是最好考慮的,不論你是1000..0001還是0111...11110,里面不論怎么反轉,最后對答案的貢獻也多一個01/10,也就是2。這種多的貢獻僅僅出現在0/1串長度大于等于三的情況。
第二種情況稍微復雜一些:先考慮0開頭的情況,也就是00..0{101010101}1..11或者00..0{101010101}0..00。這種情況下最好的處理是連著前后一個字符一起反轉:00..1{010101010}0..11于是長度喜多2。這種情況下,前面跟著一個串(長度大于等于2即可)就產生1的貢獻,后面跟著一個就產生一個貢獻。1開頭的同理。
第三種情況建立在2的基礎上:如果反轉串中間也有連續會怎樣?什么時期都不會發生,因為它作出的貢獻僅僅相當于一個單個字符。于是答案同2。
第四種情況比較有趣了:我對原答案做反轉,沒有連續的01會怎樣?那你不管怎么樣,最優答案總是原先的最長長度。
綜合以上四種情況,我們可以得到這個結論:
如果整個串里面的00/11串個數\(\le 2\),那么答案(即原先長度)加上這個串的個數;否則答案最多+2。情況1此時已經被包括在內了,因為長度為3的連續串一定有兩個00/11串。
代碼
/* * Filename: cfr334d2c.cpp* Date: 2018-11-05*/#include <bits/stdc++.h>#define INF 0x3f3f3f3f #define PB emplace_back #define MP make_pair #define fi first #define se second #define rep(i,a,b) for(repType i=(a); i<=(b); ++i) #define per(i,a,b) for(repType i=(a); i>=(b); --i) #define ZERO(x) memset(x, 0, sizeof(x)) #define MS(x,y) memset(x, y, sizeof(x)) #define ALL(x) (x).begin(), (x).end()#define QUICKIO \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0); #define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)using namespace std; using pi=pair<int,int>; using repType=int; using ll=long long; using ld=long double; using ull=unsigned long long;int dp[100005][2];int main() {int n; cin>>n;bool b[100005];string str; cin>>str;int maxlen=0,nowlen=0;bool last;int cnt=0;rep(i,0,n-1){b[i+1]=str[i]=='0';if(i==0){dp[i+1][0]=str[i]=='0';dp[i+1][1]=str[i]=='1';last=b[i+1];nowlen=1;}else{if(last==b[i+1]){nowlen++;maxlen=max(nowlen,maxlen);}else{cnt+=nowlen-1;nowlen=1;last=b[i+1];}if(str[i]=='0'){dp[i+1][1]=dp[i][1];dp[i+1][0]=dp[i][1]+1;}else{dp[i+1][1]=dp[i][0]+1;dp[i+1][0]=dp[i][0];}}}if(nowlen!=1) cnt+=nowlen-1;int ans=0;rep(i,1,n)ans=max(ans,max(dp[i][0],dp[i][1])); /*rep(i,1,n)cout<<dp[i][0]<<" ";cout<<endl;rep(i,1,n)cout<<dp[i][1]<<" ";cout<<endl; */cout<<ans+min(2,cnt)<<endl;return 0; }轉載于:https://www.cnblogs.com/samhx/p/CFR334D2C.html
總結
以上是生活随笔為你收集整理的「日常训练」Alternative Thinking(Codeforces Round #334 Div.2 C)的全部內容,希望文章能夠幫你解決所遇到的問題。