1 条题解
-
0
自动搬运
来自洛谷,原作者为

缪凌锴_Mathew
希↑望→计↓划↑可→以↑成↓功↓ | 离错真机搬运于
2025-08-24 23:06:04,当前版本为作者最后更新于2024-11-17 13:33:15,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
场上胡了一堆结论过了,证明一下这些结论。
下面我们只考虑 的情况, corner case 太多了直接跑暴力。
接下来认为删除后球会自动往前补位(即只考虑红球,蓝球不重要)。
这样一次操作必定为操作 这三个位置。
发现删除 和删除三个位置中任意两个没有区别,于是操作是对称的。
结论 :, 为奇数,最后一定能剩下权值 。
考虑 的情况, 是对称的。
-
,那么不断操作 这三个位置,选择 。
操作直到球 到达 的位置,也就是把 的球合成一个最大值。
因为 ,合出来的 ,又 ,此时操作 这三个球,选择 ,这样 。

-
,操作 ,选择 。
这样去掉了 , 是前缀最大,直接不断选择 操作即可把 移动至 。
即不断操作 ,选择 。

以上证明了可以删掉 ,对称,同理可以删掉 。
结论 :, 为偶数,最后不能剩下权值 当且仅当 两侧权值范围无交。
权值范围无交意思是 或者 。
考虑 的情况, 是对称的。
若 ,那么不断操作 这三个位置,选择 。
操作直到球 到达 的位置,也就是把 的球合成一个最大值。
因为 ,合出来的 ,又 ,此时操作 这三个球,选择 ,这样 。

又根据结论 ,可以删掉 ,这样最终剩下 。
对称地,还有可能 ,。
剩下的情况就是 或者 。
这些情况无论怎么操作,必定会操作 ,这时 是中位数,不能保留。
接下来就只用考虑 和 能不能保留,两种情况对称,只考虑 行不行。
-
不是 的中位数,删去 ,根据结论 ,可以删掉 ,剩下 。
-
是 的中位数,不妨设 。( 是对称的)
操作 或者 肯定无用,只有可能操作 。
只有 才能操作 ,于是需要一个 的 。
找到第一个 的 ,找不到无解。
-
是奇数,第一个 的 ,找不到无解。
取 min 合成 为 。
取 max 合成 为 。
,取 min 删去 和 。
,取 min 删去 和 。
剩下 ,必定有解。

-
是偶数,第一个 的 ,找不到无解。
取 min 合成 为 。
取 max 合成 为 。
同理,必定有解。

-
代码实现模拟上述过程即可,时间复杂度 。
#include<map> #include<set> #include<cmath> #include<ctime> #include<queue> #include<stack> #include<cstdio> #include<vector> #include<string> #include<bitset> #include<numeric> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; const int MAXN=1e6+10; const int N=1e6; const int INF=0x3f3f3f3f; const long long LINF=0x3f3f3f3f3f3f3f3f; const int mod=998244353; int n; int a[MAXN]; bool ans[MAXN]; int suf_max[MAXN],suf_min[MAXN]; bool f[32]; void dfs(int s){ if(f[s]){ return ; } f[s]=true; if(s==(s&-s)){ return; } for(int i=1;i<n-1;i++) { if(~s&(1<<i)){ continue; } int j=i-1,k=i+1; while(~j&&~s&(1<<j)) { j--; } while(k^n&&~s&(1<<k)) { k++; } if(~j&&k^n){ int p=a[i+1]+a[j+1]+a[k+1]-max({a[i+1],a[j+1],a[k+1]})-min({a[i+1],a[j+1],a[k+1]}); if(a[i+1]==p){ dfs(s^(1<<i)^(1<<j)); dfs(s^(1<<i)^(1<<k)); } if(a[j+1]==p){ dfs(s^(1<<j)^(1<<i)); dfs(s^(1<<j)^(1<<k)); } if(a[k+1]==p){ dfs(s^(1<<k)^(1<<i)); dfs(s^(1<<k)^(1<<j)); } } } } inline void work(){ if(a[1]<a[3]&&a[2]>a[3]){ ans[a[3]]=false; for(int i=4;i<=n;i++) { if(a[i]>a[3]){ for(int j=i+1+(i&1);j<=n;j++) { if(a[j]<a[3]){ ans[a[3]]=true; break; } } break; } } } if(a[1]>a[3]&&a[2]<a[3]){ ans[a[3]]=false; for(int i=4;i<=n;i++) { if(a[i]<a[3]){ for(int j=i+1+(i&1);j<=n;j++) { if(a[j]>a[3]){ ans[a[3]]=true; break; } } break; } } } } inline void solve(){ scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } if(n<=5){ memset(f,false,sizeof(f)); dfs((1<<n)-1); for(int i=1;i<=n;i++) { ans[a[i]]=f[1<<(i-1)]; } for(int i=1;i<=n;i++) { putchar(ans[i]+'0'); } putchar('\n'); return ; } memset(ans,true,sizeof(bool)*(n+1)); suf_max[n]=a[n]; suf_min[n]=a[n]; for(int i=n-1;i;i--) { suf_max[i]=max(suf_max[i+1],a[i]); suf_min[i]=min(suf_min[i+1],a[i]); } int pre_max=a[1],pre_min=a[1]; for(int i=1;i<=n;i++) { if(~i&1&&(pre_max<a[i]&&a[i]<suf_min[i+1]||pre_min>a[i]&&a[i]>suf_max[i+1])){ ans[a[i]]=false; } pre_max=max(pre_max,a[i]); pre_min=min(pre_min,a[i]); } work(); reverse(a+1,a+1+n); work(); for(int i=1;i<=n;i++) { putchar(ans[i]+'0'); } putchar('\n'); } signed main(){ #ifdef LOCAL freopen("data.in","r",stdin); freopen("data.out","w",stdout); atexit([](){fprintf(stderr,"%.3lfs\n",(double)clock()/CLOCKS_PER_SEC);}); #endif int t; scanf("%d",&t); while(t--) { solve(); } return 0; } -
- 1
信息
- ID
- 10766
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者