ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #767 (Div. 1)

2022-01-25 02:00:39  阅读:183  来源: 互联网

标签:int 767 Codeforces 序列 长度 Div 简短 mex 回文


A

https://codeforces.com/contest/1628/problem/A

可知前缀mex是单调递增的,字典序最大,则每次选择的mex都是最大的。

贪心地考虑,每次消去一个前缀,要求这个前缀的mex=全局的mex,且是最短的一个,这样可以使得剩余部分的mex也会尽可能大。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],b[N],c[N],aa[N];
int main()
{
	//freopen("test.in","r",stdin);
	int t;
	scanf("%d",&t);
	while (t)
	{
		t--;
		int n,mex=0;
		scanf("%d",&n);
		for (int i=1;i<=n;i++) 
		{
			scanf("%d",&a[i]);
			b[a[i]]++;
			while (b[mex]) mex++;
		}
		int p=1,i=1;
		aa[p]=mex;
		while (i<=n)
		{
			int la=i,me=0;
			while (i<=n)
			{
				c[a[i]]++;
				while (c[me]) me++;
				i++;
				if (me==mex) break;	
			}
			for (int j=la;j<i;j++) 
			{
				c[a[j]]--;
				b[a[j]]--;
				if (b[a[j]]==0) mex=min(mex,a[j]);
			}
			p++;
			aa[p]=mex;
		}
		printf("%d\n",p-1);
		for (int i=1;i<p-1;i++) printf("%d ",aa[i]);
		printf("%d\n",aa[p-1]);
		for (int i=0;i<=n;i++) b[i]=0;
	}
}

  

B

https://codeforces.com/contest/1628/problem/B

手玩的时候发现,一些很长的组合回文,也会包含一些子序列,同样可以组成回文。

考虑可以组成回文的最简短子序列,也就是要求这个子序列不再包含任何可以回文的子序列。

首先是长度为1的,显然直接回文。

然后是长度为2的,形如AA

长度为3的,可以是AAA,也可以是ABA。当然,有人肯定会说A+BA,或者AB+A,这种情况其实包含了长度为1的情况,不满足最简短的定义。

长度为4的,只有AB+BA,其他的均不是最简短的。

长度为5的,只有ABC+BA,或者AB+CBA。

长度为6的,只有ABC+CBA

更长的长度没有最简短的子序列。

理性证明一下,假设有一个长度为n的最简短子序列,只考虑这个最简短子序列的首和尾的两个小字符串,显然:

1.它们各自不能是即成的回文串,比如A,AA,AAA,ABA

2.它们长度不能相同,否则这两个小串就可以组成更简短的回文子序列。

3.情况只剩下长度分别为2和3的情况,则只能是ABC+BA或AB+CBA,也不合法

综上,没有合法情况。

所以,所有的回文子序列都可以缩小成长度不超过6的最简短回文子序列。

依次判断即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int g[10],a[N],b[N][4],q[4][N],fv[N],gv[N],f1[N];
int main()
{
	//freopen("test.in","r",stdin);
	int t;
	scanf("%d",&t);
	while (t)
	{
		g[1]=g[2]=g[3]=0;
		t--;
		int n;
		scanf("%d",&n);
		for (int i=1;i<=n;i++)
		{
			char s[5];
			scanf("%s",s+1);
			int p=strlen(s+1);
			a[i]=p;
			for (int j=1;j<=p;j++) b[i][j]=s[j]-'a';
			g[p]++;
			q[p][g[p]]=i;
		}
		if (g[1]) 
		{
			printf("YES\n");
			continue;	
		}
		int fl=0;
		for (int i=0;i<=30*30;i++) fv[i]=0,f1[i]=0;
		for (int i=1;i<=n;i++)
		{
			if (a[i]==2)
			{
				if (b[i][1]==b[i][2]) fl=1;
				fv[b[i][1]*26+b[i][2]]=1;
				//gv[b[i][1]+b[i][2]*26]=1;
				if (fv[b[i][1]+b[i][2]*26]||f1[b[i][1]+b[i][2]*26]) fl=1;
			}else 
			{
				if (b[i][1]==b[i][3]) fl=1;
				f1[b[i][1]*26+b[i][2]]=1;
				gv[b[i][3]+b[i][2]*26+b[i][1]*26*26]=1;
				if (fv[b[i][2]+b[i][3]*26]||gv[b[i][1]+b[i][2]*26+b[i][3]*26*26]) fl=1;
			}
		}
		for (int i=1;i<=n;i++) if (a[i]==3) gv[b[i][3]+b[i][2]*26+b[i][1]*26*26]=0;
		if (fl) 
		{
			printf("YES\n");
			continue;	
		}
		printf("NO\n");
	}
}

 

C

https://codeforces.com/contest/1628/problem/C

赛场上没想出来。

 

 4个这样的东西就可以了。

D1

https://codeforces.com/contest/1628/problem/D1

设f[i][j]表示i次加和j次减所能到达的最大值。

假设我们已经知道了f[i-1][j]和f[i][j-1],考虑如何确定f[i][j]

假设这一轮,给出的数字是p,则f[i][j]=max(f[i-1][j]+p,f[i][j-1]+p),由于双方都绝顶聪明,

标签:int,767,Codeforces,序列,长度,Div,简短,mex,回文
来源: https://www.cnblogs.com/lmlysklt/p/15841583.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有