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

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

#include
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. mex
  2. mex=max+1,这种情况每次插入的值都会使max加1,mex也会加1,所以每次插入的值都会大1
#include
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题
可以把负坐标翻上来
Codeforces Round #706 (Div. 2)ABCD题解_第1张图片
左边情况为sqrt(2)+sqrt(8)
右边情况为sqrt(5)+sqrt(5)
可以算出左边小于右边
那么就按照这种规律匹配就行了
记得开个long long

#include
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)Codeforces Round #706 (Div. 2)ABCD题解_第2张图片
当x取在上升序列当中时,比如选了a[k+2],那么y可以取a[k+1],x就走不了了

2)当x取在下降序列当中,同理,y选个比x小的数,x走不了
3)当x取在谷点,比如a[k+2]这个点,无论y选哪个,x都走不了Codeforces Round #706 (Div. 2)ABCD题解_第3张图片

4)Codeforces Round #706 (Div. 2)ABCD题解_第4张图片
如果x选在峰点,如a[k+2],那么又分2种情况
1.x往左走,如果y选择在a[k-1]这个点, x->a[k+1] , y->a[k] 接下来x走不了了,
可以发现只要y和x之间只要有偶数个点在x往左走的情况下,x输。
2.x往右走,那就比谁走的久了,那y可以选择离x最远的点a[k-2],x可以走3步,而y可以走4步

可以发现只要满足k-p=q-k并且k和q之间刚好有奇数的点x才能赢
Codeforces Round #706 (Div. 2)ABCD题解_第5张图片
但是需要注意的一点是,如果除了p~q之间的点,外面存在一个连续的序列长度大于等于p ~k的长度的话,y可以选在s点,这样y能走的更久。
所以满足条件的x最多只有一个
Codeforces Round #706 (Div. 2)ABCD题解_第6张图片

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

#include
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;
}

你可能感兴趣的:(题解,算法)