AGC026E - Synchronized Subsequence

AGC026E - Synchronized Subsequence

题目描述

Solution

定义 c n t [ x ] [ 0 ] , c n t [ x ] [ 1 ] cnt[x][0],cnt[x][1] 表示在前 x x 个数中0的个数和1的个数分别是多少。

然后把整个串 s s 划分为若干个子串,划分点在所有 c n t [ i ] [ 0 ] = c n t [ i ] [ 1 ] cnt[i][0]=cnt[i][1] 的位置 i i ,显然这样划分,不同的子串之间互不影响,最后合并所有子串( p i c k      o r      b a n pick\;\;or\;\;ban )就是最终答案了。

显然这样划分子串之后,可以把子串分为两类:
1.a的前缀个数始终大于b,例如:aababb。
2.a的前缀个数始终小于b,例如:bbbaabaa。

对于第一类,字典序最大的方案即为若干个ab拼接,例如:aababb最优选择是abab。
对于第二类,答案一定是它的一个后缀。

所以对于每一个子串,我们可以在 O ( n 2 ) O(n^2) 的时间内求出答案。

然后我们考虑合并答案,直接 d p dp 计算即可(我用错误的排序+特判卡过去了 h h h hhh )。

总时间复杂度 O ( n 2 ) O(n^2)

以下是错误的程序:

#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 second

using 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 ab

20
ba ab bbabaa bbbabbabbabbaaaaaa aabb aabababb
*/ 

发布了94 篇原创文章 · 获赞 6 · 访问量 8551

猜你喜欢

转载自blog.csdn.net/xmr_pursue_dreams/article/details/103434428