AGC026E - Synchronized Subsequence
题目描述
Solution
定义cnt[x][0],cnt[x][1]cnt[x][0],cnt[x][1]cnt[x][0],cnt[x][1]表示在前xxx个数中0的个数和1的个数分别是多少。
然后把整个串sss划分为若干个子串,划分点在所有cnt[i][0]=cnt[i][1]cnt[i][0]=cnt[i][1]cnt[i][0]=cnt[i][1]的位置iii,显然这样划分,不同的子串之间互不影响,最后合并所有子串(pickorbanpick\;\;or\;\;banpickorban)就是最终答案了。
显然这样划分子串之后,可以把子串分为两类:
1.a的前缀个数始终大于b,例如:aababb。
2.a的前缀个数始终小于b,例如:bbbaabaa。
对于第一类,字典序最大的方案即为若干个ab拼接,例如:aababb最优选择是abab。
对于第二类,答案一定是它的一个后缀。
所以对于每一个子串,我们可以在O(n2)O(n^2)O(n2)的时间内求出答案。
然后我们考虑合并答案,直接dpdpdp计算即可(我用错误的排序+特判卡过去了hhhhhhhhh)。
总时间复杂度O(n2)O(n^2)O(n2)。
以下是错误的程序:
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=998244353;
const int MAXN=6005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
char ST[MAXN>>1][MAXN],st[MAXN],ch[MAXN];
int c[MAXN],ID[MAXN],id[MAXN],cnt[2];
PR p[MAXN];
int compare(char *x,char *y)
{int lenx=strlen(x+1),leny=strlen(y+1),ans=0; bool flag=1;for (int i=3;i<=lenx;i++)if (x[i]!=x[i-2]) { flag=0; break; }for (int i=3;i<=leny;i++)if (y[i]!=y[i-2]) { flag=0; break; }if (flag){if (x[1]==y[1]&&x[2]==y[2]) return 2;}int len=max(lenx,leny);for (int i=1;i<=len;i++)if (x[i]>y[i]) return ans^1;else if (x[i]<y[i]) return ans;return 2;
}int compare(char *x,char *y,int len)
{for (int i=1;i<=len;i++)if (x[i]>y[i]) return 1;else if (x[i]<y[i]) return 0;return 2;
}
int comparec(int x,int y){ return x>y; }
void solve(int t,int l,int r)
{if (st[l]=='a'){int mx=0;for (int i=l;i<=r;i++)if (st[i]=='a'){int tmp=0;for (int j=i;j<=r;j++)if (st[j]=='a') ++tmp,j=p[id[j]].se;upmax(mx,tmp);}for (int i=1;i<=mx<<1;i+=2) ST[t][i]='a',ST[t][i+1]='b';}if (st[l]=='b'){int num=0;for (int i=l;i<=r;i++) if (st[i]=='a') c[++num]=id[i];sort(c+1,c+num+1,comparec);for (int i=1;i<=r-l+1;i++) ST[t][i]=st[i+l-1];for (int i=1;i<=num;i++){int len=0;for (int j=l;j<=r;j++)if (id[j]>=c[i]) ch[++len]=st[j];
// cout<<ch+1<<endl;if (compare(ch,ST[t],len)==1){for (int j=1;j<=len;j++) ST[t][j]=ch[j];for (int j=len+1;j<=r-l+1;j++) ST[t][j]=NULL;}}}
// cout<<ST[t]+1<<endl;
}
int compareid(int x,int y) { int t=compare(ST[x],ST[y]); return (t==1||t==2&&x<y); }
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);int n=read();scanf("%s",st+1);int numa=0,numb=0;for (int i=1;i<=n<<1;i++){if (st[i]=='a') p[++numa].fi=i,id[i]=numa;if (st[i]=='b') p[++numb].se=i,id[i]=numb;}int t=0;for (int i=1,lst=1;i<=n<<1;i++){cnt[st[i]-'a']++;if (cnt[0]==cnt[1]) ID[++t]=t,solve(t,lst,i),lst=i+1;}sort(ID+1,ID+t+1,compareid);
// cout<<endl;
// for (int i=1;i<=t;i++) cout<<ST[i]+1<<" "<<ID[i]<<endl;int smax=0;for (int i=1;i<=t;i++)if (ID[i]>smax) printf("%s",ST[ID[i]]+1),smax=ID[i]; return 0;
}
/*
10
ba ab ba ba bbabbbaaaa ab20
ba ab bbabaa bbbabbabbabbaaaaaa aabb aabababb
*/