Link.
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;}