• AGC026E


    题目大意

    一个长度2n的ab各n个的ab串,每次可以同时删第i个a和第i个b,求剩下的最大字典序的串

    n<=3000

    题解

    把a当作+1b当作-1,在前缀和为0的位置划开变成若干段,那么删只会影响到段的内部

    结论:在同一个段内,每个ab对(x,y)的x和y的大小关系相同,否则一定会经过前缀和为0的位置

    把以a开头的称为A段,b开头的称为B段,分类讨论

    对于一个A段,如果后面有B段就全删掉最优

    那么有效的A段是最大全A后缀,并且剩下的一定是abababab...的形式最优,因此贪心选即可

    对于一个B段,设第一个选的组i为(x,y),那么y+1~x-1中的b一定全选最优,于是又会往后选一些a,如此选下去最后一定会把>=i的组全选掉(因为只有结尾处前缀和为0,如果在中间停了就矛盾了)

    所以只有len/2+1种选法,暴力枚举判断即可

    之后从后往前贪心选择合并,时间复杂度O(n^2)

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define min(a,b) (a<b?a:b)
    #define ll long long
    //#define file
    using namespace std;
    
    struct type{
    	char a[6001];
    	int n;
    	void add(char ch) {a[++n]=ch;}
    } ans,s,Ans;
    int a[6001][3],c[6001][2],n,i,j,k,l,sum,tot,s1,s2;
    char st[6001];
    bool bz;
    
    bool pd(type a,type b)
    {
    	int i;
    	
    	fo(i,1,min(a.n,b.n))
    	if (a.a[a.n-i+1]!=b.a[b.n-i+1])
    	return a.a[a.n-i+1]<b.a[b.n-i+1];
    	return a.n<b.n;
    }
    
    int main()
    {
    	#ifdef file
    	freopen("agc026e.in","r",stdin);
    	#endif
    	
    	scanf("%d",&n);
    	scanf("%s",st+1);
    	
    	fo(i,1,n+n)
    	{
    		if (!sum)
    		{
    			++tot;
    			a[tot][0]=i;
    			a[tot][2]=st[i]=='b';
    		}
    		sum+=(st[i]=='a')?1:-1;
    		if (!sum) a[tot][1]=i;
    	}
    	
    	fd(l,tot,1)
    	if (!a[l][2])
    	{
    		if (!bz)
    		{
    			s1=s2=0;
    			fo(i,a[l][0],a[l][1])
    			{
    				if (st[i]=='a')
    				++s1,c[s1][0]=i;
    				else
    				++s2,c[s2][1]=i;
    			}
    			
    			k=(a[l][1]-a[l][0]+1)/2,j=0;
    			fo(i,1,k)
    			if (j<c[i][0])
    			ans.add('b'),ans.add('a'),j=c[i][1];
    		}
    	}
    	else
    	{
    		bz=1;Ans=ans;
    		fd(i,(a[l][1]-a[l][0]+1)/2,0)
    		{
    			s=ans;
    			s1=s2=0;
    			fd(j,a[l][1],a[l][0])
    			{
    				if (st[j]=='a')
    				{++s1;if (s1<=i) s.add('a');}
    				else
    				{++s2;if (s2<=i) s.add('b');}
    			}
    			if (pd(Ans,s)) Ans=s;
    		}
    		ans=Ans;
    	}
    	
    	fd(i,ans.n,1) putchar(ans.a[i]);
    	putchar('
    ');
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    windbg条件断点总结
    使用openssl命令剖析RSA私钥文件格式
    RSA读取密钥——使用openssl编程
    OPENSSL中RSA私钥文件(PEM格式)解析【一】
    电商系统架构——系统鸟瞰图
    构建高并发高可用的电商平台架构实践
    一些PHP性能的优化
    CentOS的Gearman安装
    php安装gearman扩展实现异步分步式任务
    使用 Gearman 实现分布式处理
  • 原文地址:https://www.cnblogs.com/gmh77/p/13627997.html
Copyright © 2020-2023  润新知