AtCoder AGC036E ABC String
題目鏈接
https://atcoder.jp/contests/agc036/tasks/agc036_e
題解
看了題解第一句話之后意識(shí)到這題是sb題以及我又雙叒叕智障了……
首先去掉串中相鄰的相同字符,不妨設(shè)A,B,C出現(xiàn)次數(shù)依次遞增。用\(cnt\)來表示一個(gè)字符的出現(xiàn)次數(shù)。
若\(cnt(B)=cnt(C)\), 那么可以刪去所有BC子串直至\(cnt(A)=cnt(B)=cnt(C)\),同時(shí)保證任何兩個(gè)A之間不能刪空。可以證明一定能做到,因?yàn)樽顗那闆r刪完后是ABCABC...ABCA這樣。長度上界\(3\cdot cnt(A)\)可以達(dá)到。
若\(cnt(B)<cnt(C)\), 首先我們盡量不改變A和B而去減少C. 考慮相鄰兩個(gè)A之間一定是B、C交替,有以下幾種類型:
(1) 開頭結(jié)尾都是B. 這種情況下我們什么都不能做。
(2) 開頭結(jié)尾一B一C. 這種情況下我們可以刪去開頭或結(jié)尾的C,把\(cnt(C)\)減少\(1\).
(3) 開頭結(jié)尾都是C. 如果這一段只有一個(gè)字符C且不在整個(gè)串的首尾, 我們什么都不能做,否則刪去首尾的C,把\(cnt(C)\)減少\(2\).
這樣做完后,有可能依然\(cnt(B)<cnt(C)\). 這時(shí)任何相鄰兩個(gè)A之間要么是C, 要么是BCBCBC...BCB.
我們的目標(biāo)是把\(cnt(C)-cnt(B)\)縮小到\(0\), 刪后面那種顯然是不優(yōu)的,于是只能刪去\((cnt(C)-cnt(B))\)個(gè)AC. 這樣顯然是合法且最優(yōu)的。
時(shí)間復(fù)雜度\(O(n)\).
寫起來細(xì)節(jié)還挺多……
代碼
#include<bits/stdc++.h> #define llong long long #define mkpr make_pair #define riterator reverse_iterator using namespace std;inline int read() {int x = 0,f = 1; char ch = getchar();for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}return x*f; }const int N = 1e6; char a[N+3],b[N+3]; bool f[N+3]; char permu[3],permui[3]; int cnt[3],cnt2[3]; int n,n0;bool cmp_cnt(int x,int y) {return cnt[x]<cnt[y];}void reset() {n0 = 0; for(int i=1; i<=n; i++) {if(!f[i]) b[++n0] = a[i];}n = n0; for(int i=1; i<=n; i++) a[i] = b[i]; }int main() {scanf("%s",a+1); n = strlen(a+1);for(int i=1; i<=n; i++) a[i] -= 'A';memset(f,false,sizeof(f));for(int i=2; i<=n; i++) if(a[i]==a[i-1]) f[i] = true;reset();for(int i=1; i<=n; i++) cnt[a[i]]++;for(int i=0; i<3; i++) permu[i] = i;sort(permu,permu+3,cmp_cnt); sort(cnt,cnt+3);for(int i=0; i<3; i++) permui[permu[i]] = i;for(int i=1; i<=n; i++) a[i] = permui[a[i]];int dif = cnt[2]-cnt[1];memset(f,false,sizeof(f));for(int l=(a[1]==0?2:1); l<=n;){int r = l;while(r<n&&a[r+1]!=0) {r++;}if(dif>0&&!(l==r&&l>1&&r<n)&&!(a[l]==1&&a[r]==1)){if(a[l]==2&&dif>0) {f[l] = true; dif--;}if(r>l&&a[r]==2&&dif>0) {f[r] = true; dif--;}}l = r+2;}reset();if(dif>0){memset(f,false,sizeof(f));for(int l=(a[1]==0?2:1); l<=n;){int r = l;while(r<n&&a[r+1]!=0) {r++;}if(l==r&&a[l]==2&&l>1&&r<n&&dif>0) {f[l] = f[l-1] = true; dif--;}l = r+2;}reset();}memset(cnt,0,sizeof(cnt));for(int i=1; i<=n; i++) cnt[a[i]]++;dif = cnt[1]-cnt[0];memset(f,false,sizeof(f));for(int l=(a[1]==0?2:1); l<=n;){int r = l;while(r<n&&a[r+1]!=0) {r++;}int rst = r-l+1;for(int i=l+1; i<=r; i++){if(a[i]==2&&a[i-1]==1&&dif>0&&(l==1||r==n||rst>2)) {f[i] = f[i-1] = true; dif--; rst-=2;}}l = r+2;}reset();for(int i=1; i<=n; i++) printf("%c",permu[a[i]]+'A'); puts("");return 0; } 與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的AtCoder AGC036E ABC String的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AtCoder AGC030E Less
- 下一篇: AtCoder AGC030C Colo