CF2229G Roadworks

\(\text{OI}\) 退役后第一篇题解!

思路

考虑在村庄间移动的过程,容易发现一定形如:直接走到某个点,在这个点停留一会,走到另一个更大的点,再停留一会......

也就是停留的点一定是行走路径上最大的那个。

容易想到把路径拆分成从某个点到其左边或右边第一个更大值,随后在这个点停留几天(可能是 \(0\))的几段。

并且到达新村庄的时间一定是允许范围内最小的,因为在新村庄停留一定更优。

\(t_i\) 表示到达 \(i\) 的最小时间,\(f_i\) 表示在时间最小的情况下的最大满意度。

\(t_i\) 可以直接算出来,就是从 \(x\) 出发到 \(i\) 的最小时间,现在只需计算 \(f_i\) 即可。

可以类似 dijkstra 地转移,不过也无须如此麻烦,我们可以直接钦定一个转移顺序,例如按 \(h\) 值从小到大转移。

统计答案是简单的,这样就能做到 \(\Theta(n \log n)\),瓶颈在于排序。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mid ((l+r)>>1)
#define lowbit(x) ((x)&(-x))
#define all(x) (x).begin(),(x).end()
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define add(x,y) (x=((x+y>=mod)?(x+y-mod):(x+y)))
int const N=2e5+10;
int n,k,x,top,S[N],t[N],f[N],h[N],d[N],L[N],R[N],id[N],qz[N];
inline void solve(){
	  cin>>n>>k>>x;
  	rep(i,1,n) cin>>h[i],id[i]=i;
  	rep(i,1,n-1) cin>>d[i];
  	rep(i,1,n) qz[i]=qz[i-1]+h[i];
  	top=0;
  	rep(i,1,n) L[i]=R[i]=f[i]=0;
  	rep(i,1,n){
  		  while (top && h[i]>h[S[top]]) R[S[top]]=i,--top;
    		S[++top]=i;
  	}
  	top=0;
  	per(i,n,1){
  		  while (top && h[i]>h[S[top]]) L[S[top]]=i,--top;
    		S[++top]=i;
  	}
  	sort(id+1,id+n+1,[](int x,int y){return h[x]<h[y];});
  	t[x]=0;
  	rep(i,x+1,n) t[i]=max(t[i-1]+1,d[i-1]);
  	per(i,x-1,1) t[i]=max(t[i+1]+1,d[i]);
  	t[x]=1;
  	int ans=h[x]*k;
  	rep(i,1,n){
  		  int nw=id[i];
    		ans=max(ans,f[nw]+(k-t[nw]+1)*h[nw]);
    		if (L[nw]){
    			  int to=L[nw];
      			if (nw-to<=t[to]-t[nw]) f[to]=max(f[to],f[nw]+(t[to]-t[nw]-(nw-to)+1)*h[nw]+qz[nw-1]-qz[to]);
    		}
    		if (R[nw]){
    			  int to=R[nw];
      			if (to-nw<=t[to]-t[nw]) f[to]=max(f[to],f[nw]+(t[to]-t[nw]-(to-nw)+1)*h[nw]+qz[to-1]-qz[nw]);
    		}
  	}
  	cout<<ans<<'\n';
}
signed main(){
	  ios::sync_with_stdio(false);
  	cin.tie(nullptr),cout.tie(nullptr);
  	int t=1;
  	cin>>t;
  	while (t--) solve();
  //	cerr<<"Time:"<<(double)clock()/CLOCKS_PER_SEC<<"s\n";
  	return 0;
}
posted @ 2026-07-01 13:35  Tx_Lcy  阅读(19)  评论(0)    收藏  举报