Codeforces Round #706 (Div. 2)ABCD题解

A题,找回文,中间部分可以不满足回文要求

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int t,n,k,a[N];
char s[110];
int main()
{
    
    
	scanf("%d",&t);
	while(t--)
	{
    
    
		scanf("%d%d%s",&n,&k,s+1);
		int x=0;
		for(int i=1;i<=n/2;i++)
		{
    
    
			if(s[i]!=s[n-i+1])break;
			x++;
		}
		if(2*x==n)x--;
		if(k<=x)puts("YES");
		else puts("NO");
	}
	return 0;
}

B题,两种情况

  1. m e x < m a x mex<max mex<max,新插入的值不会改变 m e x mex mex m a x max max,故只需判断第一次插入的值是否存在即可
  2. m e x = m a x + 1 mex=max+1 mex=max+1,这种情况每次插入的值都会使 m a x max max加1, m e x mex mex也会加1,所以每次插入的值都会大1
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int t,n,k,a[N];
unordered_map<int,bool>mp;
int main()
{
    
    
	scanf("%d",&t);
	while(t--)
	{
    
    
		mp.clear();
		int m=0,cnt=0,p=0;
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;i++)scanf("%d",&a[i]);
		sort(a+1,a+1+n);
		bool f=1;
		a[0]=-1;
		for(int i=1;i<=n;i++)
		{
    
    
			if(!mp.count(a[i]))
			{
    
    
				if(a[i]-a[i-1]>1&&f)
				{
    
    
					p=a[i-1]+1;
					f=0;
				}
				cnt++;
				mp[a[i]]=1;
			}
			m=max(m,a[i]);
		}
		if(m+1==cnt)cout<<cnt+k<<endl;
		else cout<<cnt+(k>0)-(mp.count((1+p+a[n])>>1))<<endl;
	}
	return 0;
}

C题,可以把负坐标翻上来
在这里插入图片描述
左边情况为 2 + 8 \sqrt2+\sqrt8 2 +8 ,右边情况为 5 + 5 \sqrt5+\sqrt5 5 +5
可以算出左边小于右边
那么就按照这种规律匹配就行了
记得开个 l o n g l o n g long long longlong

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int t,n,k,a[N],b[N];
int main()
{
    
    
	scanf("%d",&t);
	while(t--)
	{
    
    
		scanf("%d",&n);
		int c1=0,c2=0;
		double ans=0;
		for(int i=1;i<=2*n;i++)
		{
    
    
			int x,y;
			scanf("%d%d",&x,&y);
			if(x==0)a[++c1]=abs(y);
			else b[++c2]=abs(x);
		}
		sort(a+1,a+1+c1);
		sort(b+1,b+1+c2);
		for(int i=1;i<=n;i++)
			ans+=sqrt((ll)a[i]*a[i]+(ll)b[i]*b[i]);
		printf("%.12lf\n",ans);
	}
	return 0;
}

D题,分4种情况
在这里插入图片描述

  1. x x x取在上升序列当中时,比如选了 a [ k + 2 ] a[k+2] a[k+2],那么 y y y可以取 a [ k + 1 ] a[k+1] a[k+1] x x x就走不了了

  2. x x x取在下降序列当中,同理, y y y选个比 x x x小的数, x x x走不了

  3. x x x取在谷点,比如 a [ k + 2 ] a[k+2] a[k+2]这个点,无论 y y y选哪个, x x x都走不了在这里插入图片描述

在这里插入图片描述
4) 如果 x x x选在峰点,如 a [ k + 2 ] a[k+2] a[k+2],那么又分2种情况

  1. x x x往左走,如果 y y y选择在 a [ k − 1 ] a[k-1] a[k1]这个点, x − > a [ k + 1 ] x->a[k+1] x>a[k+1] y − > a [ k ] y->a[k] y>a[k] 接下来 x x x走不了了,
    可以发现只要 y y y x x x之间只要有偶数个点在 x x x往左走的情况下, x x x输。
  2. x x x往右走,那就比谁走的久了,那 y y y可以选择离 x x x最远的点 a [ k − 2 ] a[k-2] a[k2] x x x可以走3步,而y可以走4步

可以发现只要满足 k − p = q − k k-p=q-k kp=qk并且 k k k q q q之间刚好有奇数的点 x x x才能赢
在这里插入图片描述
但是需要注意的一点是,如果除了 p p p ~ q q q之间的点,外面存在一个连续的序列长度大于等于 p p p ~ k k k的长度的话, y y y可以选在 s s s点,这样 y y y能走的更久,所以满足条件的 x x x最多只有一个
在这里插入图片描述

我的代码实现比较麻烦,先求出满足 k − p = q − k k-p=q-k kp=qk并且 k k k q q q之间刚好有奇数的点的峰的最长连续长度,
然后再找整个数组中最长的连续长度,再进行比较

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int t,n,k,a[N],b[N],c[N];
int main()
{
    
    
	int cnt=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=1,c[i]=1;
	for(int i=2;i<=n;i++)
		if(a[i]>a[i-1])b[i]=b[i-1]+1;
	b[n+1]=110000;
	int m,p,pp,mm=0;
	bool f1=0,f2=0;
	for(int i=2;i<=n+1;i++)
	{
    
    
		if(b[i]<b[i-1])f1=1,m=b[i-1],p=i;
		else if(b[i]>b[i-1]&&f1)f2=1,pp=i;
		if(f1&&f2)
		{
    
    
			f1=f2=0;
			if(pp-p==m-1&&(m&1))mm=max(mm,m);
		}
	}
	for(int i=n-1;i>=1;i--)
		if(a[i]>a[i+1])c[i]=c[i+1]+1;
	sort(c+1,c+1+n,greater<int>());
	sort(b+1,b+1+n,greater<int>());
	for(int i=1;i<=5;i++)a[i]=c[i];
	for(int i=1;i<=5;i++)a[i+5]=b[i];
	sort(a+1,a+1+10,greater<int>());
	if(a[3]<mm)puts("1");
	else puts("0");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46001550/article/details/114651232