题解:P9893 [ICPC 2018 Qingdao R] Soldier Game
借鉴 CF1919F2 的思想。
我们尝试固定最小值,让最大值最小。
容易发现可能更新答案的最小值只会有 \(2n-1\) 个。
直接对 \(a\) 建线段树,对于每个节点维护 \(dp[p][1/0][1/0]\) 表示 \(p\) 节点所管辖的区间 \([l,r]\) 中 \(l\) \([\)是\(/\)否\(]\) 和 \(l-1\) 在同一段,\(r\) \([\)是\(/\)否\(]\) 和 \(r+1\) 在同一段。
初始化:
\(a[0]=a[n+1]=inf\)
叶子节点:
dp[p][0][0]=a[l]
dp[p][0][1]=a[l]+a[l+1]
dp[p][1][0]=a[l-1]+a[l]
dp[p][1][1]=inf
非叶子节点直接 pushup,固定左右两端点状态,枚举中间状态,取最小值。
void pushup(int p)
{
dp[p][0][0]=min({max(dp[lp][0][0],dp[rp][0][0]),max(dp[lp][0][1],dp[rp][1][0])});
dp[p][0][1]=min({max(dp[lp][0][0],dp[rp][0][1]),max(dp[lp][0][1],dp[rp][1][1])});
dp[p][1][0]=min({max(dp[lp][1][0],dp[rp][0][0]),max(dp[lp][1][1],dp[rp][1][0])});
dp[p][1][1]=min({max(dp[lp][1][0],dp[rp][0][1]),max(dp[lp][1][1],dp[rp][1][1])});
}
每次固定最小值 \(x\),调用 \(dp[rt][0][0]\) 即可得到最小的最大值。
然后做所有 \(a[i]=x\) 的 \(i\) 的单点修改和 \(a[i]+a[i-1]=x\) 的 \(i\) 和 \(i-1\) 的单点修改。
实现时将线段树上叶子 \(p\)(管辖 \([i,i]\))的 \(dp[p][0][0]\) 设为 \(inf\) 即可。
还需要判断若 \(a[i-1]+a[i]<=x\),则令 \(dp[p][1][0]=inf\);若 \(a[i]+a[i+1]<=x\),则令 \(dp[p][0][1]=inf\)。表示不能这么选。
发现我们只会修改最多 \(n+2(n-1)\) 次。复杂度大常数 \(O(n \log n)\),可以通过。
注意我们需要将最小值去重,否则可以被卡到 \(O(n^2 \log n)\)。
Code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
int x=0,c=getchar(),f=0;
for(;c>'9'||c<'0';f=c=='-',c=getchar());
for(;c>='0'&&c<='9';c=getchar())
x=(x<<1)+(x<<3)+(c^48);
return f?-x:x;
}
inline void write(int x)
{
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar(x%10+'0');
}
int n;
int a[1<<20];
int b[1<<20];
const int N=2e5+5,inf=1e18+1;
vector<int> v[N<<1];
vector<int> ans;
unordered_map<int,int> id;
#define lp (p<<1)
#define rp ((p<<1)|1)
int dp[N<<2][2][2];
void pushup(int p)
{
dp[p][0][0]=min({max(dp[lp][0][0],dp[rp][0][0]),max(dp[lp][0][1],dp[rp][1][0])});
dp[p][0][1]=min({max(dp[lp][0][0],dp[rp][0][1]),max(dp[lp][0][1],dp[rp][1][1])});
dp[p][1][0]=min({max(dp[lp][1][0],dp[rp][0][0]),max(dp[lp][1][1],dp[rp][1][0])});
dp[p][1][1]=min({max(dp[lp][1][0],dp[rp][0][1]),max(dp[lp][1][1],dp[rp][1][1])});
}
void build(int l,int r,int p)
{
memset(dp[p],0,sizeof(dp[p]));
if(l==r)
{
dp[p][0][0]=a[l];
dp[p][0][1]=(l==n?inf:(a[l]+a[l+1]));
dp[p][1][0]=(l==1?inf:(a[l]+a[l-1]));
dp[p][1][1]=inf;
return;
}
int mid=(l+r)>>1;
build(l,mid,lp);
build(mid+1,r,rp);
pushup(p);
}
bool vis[N];
void change(int l,int r,int x,int minn,int p)
{
if(l==r)
{
if(a[l]<=minn) dp[p][0][0]=inf;
if(l>1&&a[l]+a[l-1]<=minn) dp[p][1][0]=inf;//,change(1,n,l-1,minn,1);
if(l<n&&a[l]+a[l+1]<=minn) dp[p][0][1]=inf;//,change(1,n,l+1,minn,1);
if(dp[p][0][0]==dp[p][1][0]&&dp[p][1][0]==dp[p][0][1]&&dp[p][0][0]==inf) vis[p]=1;
return;
}
int mid=(l+r)>>1;
if(x<=mid) change(l,mid,x,minn,lp);
else change(mid+1,r,x,minn,rp);
pushup(p);
}
void Deb(int l,int r,int p)
{
cout<<"["<<l<<","<<r<<"]"<<" p="<<p<<"\n";
cout<<"dp[p][0][0]="<<dp[p][0][0]<<"\n";
cout<<"dp[p][0][1]="<<dp[p][0][1]<<"\n";
cout<<"dp[p][1][0]="<<dp[p][1][0]<<"\n";
cout<<"dp[p][1][1]="<<dp[p][1][1]<<"\n\n";
int mid=(l+r)>>1;
if(l==r) return;
Deb(l,mid,lp);
Deb(mid+1,r,rp);
}
void solve(int T)
{
for(int i=1;i<=n;i++) vis[i]=0;
id.clear();
ans.clear();
n=read();
a[0]=-inf;
a[n+1]=inf;
for(int i=1;i<=n;i++) a[i]=read(),b[i]=a[i];
sort(b+1,b+1+n);
b[0]=-inf;
b[n+1]=inf;
int tot=0;
for(int i=1;i<=n;i++)
if(b[i]!=b[i-1]) id[b[i]]=++tot,ans.push_back(b[i]);
for(int i=1;i<=n;i++)
v[id[a[i]]].push_back(i);
for(int i=2;i<=n;i++) if(!id[a[i-1]+a[i]]) id[a[i-1]+a[i]]=++tot,ans.push_back(a[i-1]+a[i]);
sort(ans.begin(),ans.end());
int totnum=tot;
for(int i=2;i<=n;i++)
{
v[id[a[i]+a[i-1]]].push_back(i-1);
v[id[a[i]+a[i-1]]].push_back(i);
}
int ans_min=inf;
build(1,n,1);
for(int i=1;i<=n;i++) vis[i]=0;
for(int i:ans)
{
int nw=id[i];
if(dp[1][0][0]>=inf) break;
ans_min=min(ans_min,dp[1][0][0]-i);
for(int pos:v[nw]) if(!vis[pos]) change(1,n,pos,i,1);
}
for(int i=0;i<=tot;i++) v[i].clear();
ans.clear();
cout<<ans_min<<"\n";
}
signed main()
{
int T=read();
for(int i=1;i<=T;i++)solve(i);
return 0;
}
以下是博客签名,正文无关
本文来自博客园,作者:Wy_x,转载请在文首注明原文链接:https://www.cnblogs.com/Wy-x/articles/19144221
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC-BY-NC-SA 4.0 协议)进行许可。

浙公网安备 33010602011771号