CF Round #850 (Div.2) 解题报告 (A~C)

Codeforces Round 850 (Div.2)

Contest link

My result

代码不含多测相关内容。

A1. Non-alternating Deck (easy version)

直接模拟发牌过程即可。

ll n,ans,a,b,s,i,j;
void Solve()
{
	cin>>n;
	a=b=s=0;
	for(i=0,j=1;i<n;j++)
	{
		ll i1=i;
		i=min(i+j,n);
		if(s%4==0||s%4==3)a+=i-i1;else b+=i-i1;
		s++;
	}
	cout<<a<<" "<<b<<endl;
}

A2. Alternating Deck (hard version)

本来以为 A2 就是增大 \(n\) 的范围

这次,我们考虑一张一张地发牌。直接算出这张牌发给谁,是什么颜色即可。预先打表出答案,每次寻味直接输出。

int f[1000005][4];
int x(int t){return t%4==1||t%4==2;}
void Init()
{
	int s=0,t=0;
	for(int i=1,nxt=1,j=1;i<=1000000;i++)
	{
		for(int j=0;j<4;j++)f[i][j]=f[i-1][j];
		f[i][s+x(t)*2]++;
		s=!s;
		if(i==nxt)t++,j++,nxt+=j;
	}
}
int n;
void Solve()
{
	cin>>n;
	for(int i=0;i<4;i++)cout<<f[n][i]<<" ";
	cout<<endl;
}

B. Cake Assembly Line

因为只能喷一次,所以第 \(i\) 个蛋糕肯定会被第 \(i\) 个机器喷上巧克力。于是,我们可以算出第 \(i\) 个蛋糕移动到的坐标的范围。易知 \(l_i=b_i-w+h,r_i=b_i+w-h\)。再将其减去 \(a_i\),就可以知道蛋糕移动的范围。于是我们可以算出偏移量的最小值 \(mi\) 与最大值 \(ma\),当且仅当 \(mi\le ma\) 时有解。

const int N=100005;
int n;
ll h,w,a[N],b[N],mi,ma,l[N],r[N];
void Solve()
{
	cin>>n>>w>>h;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)cin>>b[i];
	mi=INT_MIN,ma=INT_MAX;
	for(int i=1;i<=n;i++)
		l[i]=b[i]-w+h,r[i]=b[i]+w-h;
	for(int i=1;i<=n;i++)
		mi=max(mi,a[i]-r[i]),ma=min(ma,a[i]-l[i]);
	cout<<(mi<=ma?"YES":"NO")<<endl;
}

C. Monsters (easy version)

显然,要让操作 1 的次数尽量少,就要让操作 2 的效果尽量大。不妨将操作 2 放在最后做一次,然后将怪物全部杀死。

如何使操作 2 的效果尽量大?要让他打出更多的“连击”。也就是说,每削一次至少杀死一只怪物。

也就是说,剩下的怪物里,假设血量剩余最多的怪物血量为 \(x\),那么血量为 \(1\sim x\) 的怪物必须全部有至少一个。

那么解法就出来了:先将 \(a\) 从小到大排序,然后遍历每只怪物,如果和上一只血量接不上,就将他攻到比上一个怪物多 1 滴血。

const int N=200005;
int n,a[N];
ll ans;
void Solve()
{
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	sort(a+1,a+n+1);
	ans=0;
	for(int i=1,j=1;i<=n;i++)
	{
		if(a[i]<j)continue;
		ans+=a[i]-j;
		j++;
	}
	cout<<ans<<endl;
}
posted @ 2023-02-08 21:20  No_Play_Yes_Splay  阅读(29)  评论(0编辑  收藏  举报