AtCoder Grand Contest 041(坑)

Preface

花了两个晚自习加上一个中午和一个周末晚上和大量的自习课时间打完了

ABE还勉强算自己想的都是陈指导想的,C看了点提示在同学的帮助下Rush出来了,D只能自己想出\(O(n^3)\)暴力,F想了两天连状态都不知道怎么设看了题解直呼内行

总结:水平太次,建议回炉重造


A - Table Tennis Training

签到题,注意到如果两个人之间的位置差是偶数的话直接走就好了

否则就是两种情况:

  1. 在最左边或最右边相遇(先到的人可以一直等后面的人到)
  2. 在左边的人到了最左边之后等待一轮,然后在向右走与右边的人碰头;右边的人同理

讨论一下取最小值即可,WA了一发没看见要开long long

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
long long n,a,b;
int main()
{
	scanf("%lld%lld%lld",&n,&a,&b);
	if ((b-a)%2==0) return printf("%lld",(b-a)/2),0;
	long long res=min(b-1,n-a); res=min(res,min((a+b)/2,(2*n-a-b+1)/2));
	return printf("%lld",res),0;
}


B - Voting Judges

简单分析题。首先我们发现给\(a_i\)从大到小排序后前\(p\)个数是一定合法的(废话)

然后考虑从\(p+1\)开始枚举最小的能被加到前\(p\)的位置\(i\),贪心地想我们肯定只要加到第\(p\)个地方即可

考虑这个位置每次都被加\(1\),那么剩下的\(v-1\)次怎么分配?

显然对于所有位置在它之后以及前\(p-1\)个数都可以随便加,那么我们给这些数也加满

那么问题来了,如果操作次数还有多怎么办,只能填在\([p+1,i)\)之间了

考虑判断不合法时怎么操作,我们求出\(S=\sum_{j=p+1}^{i-1} a_j\),然后判断\((a_i+m)\times (i-p)-S\)与剩下来的增加次数的关系

为什么可以这么做呢,因为\([p+1,i)\)中的数都\(\ge a_i\),那么每个数都是可以经过\(m\)次操作超过\(a_i+m\)的,那么极限情况就是全加到\(a_i+m\)

时间复杂度\(O(n\log n)\),因为要排序。然后有一个坑点,要判断\(a_i+m\ge a_p\),刚开始石乐志没判WA了两发

#include<cstdio>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int n,a[N],m,v,p; long long sum[N];
inline bool cmp(CI x,CI y)
{
	return x>y;
}
int main()
{
	RI i; for (scanf("%d%d%d%d",&n,&m,&v,&p),i=1;i<=n;++i) scanf("%d",&a[i]);
	for (sort(a+1,a+n+1,cmp),i=1;i<=n;++i) sum[i]=sum[i-1]+a[i];
	for (i=p+1;i<=n;++i)
	{
		int dlt=max(0,v-(p+n-i)); long long tot=sum[i-1]-sum[p-1];
		if (a[i]+m<a[p]||1LL*(i-p)*(a[i]+m)+1-tot<=1LL*dlt*m) return printf("%d",i-1),0;
	}
	return printf("%d",n),0;
}


C - Domino Quality

手玩构造题。这种题目看完就想着先手玩小的看看规律

然后和陈指导Rush了快1hour然后只搞出了\(n=3,4,5\)的情况,感觉没什么规律

瞄了一眼题解,原来\(n\)是偶数可以构造,回班之后开始尝试,竟然很快就Rush出来了(自习课加智商),以\(n=8\)为例(一看就知道怎么构造的说):

aa....cd
bb....cd
cdaa....
cdbb....
..cdaa..
..cdbb..
....cdaa
....cdbb

同时也容易想到\(n|3\)时可以直接用\(3\times 3\)的拼出来,那么现在就考虑\(n \not |\ 3\)的奇数,考虑因为我们偶数的构造法行列都是三个,然后\(n=5\)时的答案:

aabc.
..bcd
fee.d
f.ghh
iigjj

也是行列三个,容易想到我们先把左上角填一个\(5\times 5\)的,然后在右下角填一个\((n-5)\times (n-5)\)

然后大功告成?发现当\(n=7\)的时候就GG了,那怎么办?

手玩构造\(n=7\)的答案(感谢无私奉献的同桌):

ab...c.
ab...c.
..dee.f
..d.g.f
..hhg.i
jj..kki
llmm.nn

然后终于做完了,WA了一发在拼图的时候把偶数的最后一块填到第一行去了。。。

#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
const int N=1005;
char
tp5[N][N]={
			"aabc.",
			"..bcd",
			"fee.d",
			"f.ghh",
			"iigjj"
		},
tp7[N][N]={
			"ab...c.",
			"ab...c.",
			"..dee.f",
			"..d.g.f",
			"..hhg.i",
			"jj..kki",
			"llmm.nn"
		};
int n; char a[N][N];
inline void odd_paint(CI sx=0)
{
	for (RI i=sx;i<n;i+=2)
	a[i][i]=a[i][i+1]='a',a[i+1>=n?i+1-n+sx:i+1][i]=a[i+1>=n?i+1-n+sx:i+1][i+1]='b',
	a[i+2>=n?i+2-n+sx:i+2][i]=a[i+3>=n?i+3-n+sx:i+3][i]='c',a[i+2>=n?i+2-n+sx:i+2][i+1]=a[i+3>=n?i+3-n+sx:i+3][i+1]='d';
}
inline void print(CI n,char c[N][N])
{
	for (RI i=0;i<n;++i)
	{
		for (RI j=0;j<n;++j) putchar(c[i][j]); if (i!=n-1) putchar('\n');
	}
}
int main()
{
	RI i,j; scanf("%d",&n); if (n==2) return puts("-1"),0;
	if (n==5) return print(5,tp5),0;
	if (n==7) return print(7,tp7),0;
	for (i=0;i<n;++i) for (j=0;j<n;++j) a[i][j]='.';
	if (n%3==0)
	{
		for (i=0;i<n;i+=3) for (j=0;j<n;j+=3)
		a[i][j]=a[i][j+1]='a',a[i+1][j+2]=a[i+2][j+2]='b';
		return print(n,a),0;
	}
	if (n%2==0) return odd_paint(),print(n,a),0;
	for (i=0;i<5;++i) for (j=0;j<5;++j) a[i][j]=tp5[i][j];
	return odd_paint(5),print(n,a),0;
}


D - Problem Scores

Rush了C之后看了看DE题面就滚回班了,连着想了两天然后只出了一个\(O(n^4)\)(然后被陈指导指点了一下复杂度发现是\(O(n^3)\)的)

首先我们考虑直接令\(a_i\)增序,然后记\(S_i=\sum_{j=1}^i a_j\),那么题中的条件等价于:

\[\forall k\in (1,n-1),S_k>S_{n}-S_{n-k+1}\Leftrightarrow S_k+S_{n-k+1}>S_n \]

显然由于\(S_k+S_{n-k+1}\)的对称性,我们只要做一半即可,换句话说只要前\(\lfloor\frac{n+1}{2}\rfloor\)

猜你喜欢

转载自www.cnblogs.com/cjjsb/p/12902274.html