GYM 102452E 题解

Codeforces

Description.

给定一个排列,每次可以选出 \(3\) 个数并删掉最大和最小的。
问哪些数能存活到最后。

Solution.

首先考虑那个中为数经典套路,大于它的 \(+1\) 小于它的 \(-1\)
首先,考虑如果序列和为 \(0\) 那肯定可以。
就考虑肯定有相连三个位置存在 \(+1\)\(-1\),那操作这三个位置,然后就规约成子问题。
那我们需要减少 \(+1\)\(-1\) 的数量。
发现连着的三个 \(+1\)\(-1\) 可以减少两个,而且这是唯一方法。
所以直接扫一遍,每次如果遇到一个需要消的 \(tp\leftarrow tp+1\),如果遇到一个敌人就 \(tp\leftarrow tp-1\) (可以用两个同伴去牺牲掉换掉。
遇到当前为 \(0\) 的那个数直接全部清空,因为不能跨过它进行操作,它必须留到最后。
然后就做完了。

Coding.

点击查看不行代码
//是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}
template<typename T,typename...L>inline void read(T &x,L&...ln) {read(x),read(ln...);}/*}}}*/
int n,a[10005],fg[10005];
inline int sign(int x) {return x<0?-1:x>0?1:0;}
inline void solve()
{
	read(n);for(int i=1;i<=n;i++) read(a[i]);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++) fg[j]=sign(a[j]-a[i]);
		int sm=0,tp=0;for(int j=1;j<=n;j++) sm+=fg[j];
		int sig=sign(sm);for(int j=1;j<=n;j++)
		{
			if(fg[j]==0) tp=0;else if(fg[j]!=sig) tp=max(tp-1,0);else tp++;
			if(tp>=3) {sm-=2*sig,tp-=2;if(!sm) break;}
		}
		//putchar('\n');for(int j=1;j<=n;j++) printf("%d%c",fg[j],j==n?'\n':' ');
		if(sm) putchar('0');else putchar('1');
	}putchar('\n');
}
int main() {int Ca;for(read(Ca);Ca--;) solve();return 0;}
posted @ 2021-10-04 20:55  Peal_Frog  阅读(32)  评论(1编辑  收藏  举报