题解:P12546 [UOI 2025] Convex Array
首先将数组按从小到大的顺序排序。
那么合法的重排一定形如
这样我们可以从小到大加入
设
做一个简单的观察:
做一个简单的优化:我们没必要记录
考虑最大值与次大值(的下标)构成的形式,分讨
-
(i,i-1,b,c) -
(i,i-2,i-1,c) -
(i,c,i-1,i-2)
容易发现只有这三种形式,对于当前的
- 放在第一个序列
条件为
- 放在第二个序列
条件为
如果过滤掉没用的状态,则构成形如 set 维护加入和删除,使用 lower_bound 查找前驱即可,
#include<bits/stdc++.h>
#define ll long long
#define L x<<1
#define R x<<1|1
#define mid ((l+r)>>1)
#define lc L,l,mid
#define rc R,mid+1,r
#define Root 1,1,n
#define OK Ll<=l&&r<=Rr
#define rep(x,y,z) for(int x=(y);x<=(z);x++)
#define per(x,y,z) for(int x=(y);x>=(z);x--)
#define repn(x) rep(x,1,n)
#define repm(x) rep(x,1,m)
#define pb push_back
#define e(x) for(int i=h[x],y=to[i];i;i=nxt[i],y=to[i])
#define E(x) for(auto y:p[x])
#define Pi pair<int,int>
#define ui unsigned ll
#define yy return puts("Yes"),void()
#define nn return puts("No"),void()
#define YY puts("Yes"),exit(0)
#define NN puts("No"),exit(0)
inline int read(){int s=0,w=1;char c=getchar();while(c<48||c>57) {if(c=='-') w=-1;c=getchar();}while(c>=48&&c<=57)s=(s<<1)+(s<<3)+c-48,c=getchar();return s*w;}
inline void pf(int x){if(x<0) putchar('-'),x=-x;if(x>9)pf(x/10);putchar(x%10+48);}
using namespace std;
const int N=5e5+5,M=1e7+5,inf=(1LL<<31)-1,mod=998244353;
const ll llf=1e18;
inline void add(int &a,int b){if(b<0)b+=mod;((a+=b)>=mod) and (a-=mod);}
inline int Add(int a,int b){return add(a,b),a;}
inline int mul(int a,int b){add(b,mod);return 1LL*a*b%mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline void red(int &a,int b){add(a,mod-b);}
inline int Red(int a,int b){return red(a,b),a;}
inline int qp(int a,ll b){if(!b)return 1;int c=qp(a,b>>1LL);Mul(c,c);if(b&1)Mul(c,a);return c;}
inline int INV(int x){return qp(x,mod-2);}
int n,a[N],F1=-1,F2=-1,G1,G2;
map<int,int>P;
inline int Get(int x){
if(P.empty())return -1;
auto it=P.upper_bound(x);
if(it==P.begin())return -1;
it--;
return (*it).second;
}
inline void Insert(int b,int c){
int W=2*a[b]-a[c],k=Get(W);
if(k>=b)return;
while(1){
if(P.empty())break;
auto it=P.upper_bound(W);
if(it==P.end())break;
int k=(*it).second,id=(*it).first;
if(k>b)break;
P.erase(id);
}
P[W]=b;
}
inline void Main(){
n=read(),F1=F2=-1;
repn(i)a[i]=read();
sort(a+1,a+n+1),P.clear(),P[a[1]]=1;
/*
(i,i-1,b,c) //P
(i,i-2,i-1,c) //F1
(i,c,i-1,i-2) //F2
*/
rep(i,3,n){
G1=G2=-1;
int Mx=-1;
Mx=Get(a[i]);
//转移F1
// (i,i-1,b,c)->(i,b,i-1,i-2)
G2=Mx;
if(a[i]+a[i-2]<a[i-1]*2)P.clear();//(i,i-1,b,c)
if(F1!=-1){
//(i,i-2,i-1,c)
if(a[i]-a[i-1]>=a[i-1]-a[i-3])Insert(i-2,F1);//(i,i-1,i-2,c)
if(a[i]-a[i-2]>=a[i-2]-a[F1])G1=max(G1,i-3);//(i,i-2,i-1,i-3)
}
//转移F2
if(F2!=-1){
//(i,c,i-1,i-2)
if(a[i]-a[i-1]>=a[i-1]-a[F2])Insert(i-2,i-3);//(i,i-1,i-2,i-3)
if(a[i]-a[i-2]>=a[i-2]-a[i-3])G1=max(G1,F2);//(i,i-2,i-1,c)
}
F1=G1,F2=G2;
}
if(F1!=-1||F2!=-1||!P.empty())puts("YES");
else puts("NO");
}
signed main(){
int T=read();
while(T--)Main();
return 0;
}