P4734 [BalticOI 2015] Hacker
  BLQ4mFeCsIAS 10天前 29 0

题目大意

详细题目传送门

思路

对于这种题目一般可以先断环成链。

发现先手所得到的值是一个长度为 \(\lceil \frac{n}{2}\rceil\) 的区间,我们希望让它的元素之和能取到最大,但发现后手会让我们取不到最大。

假设我们从第 \(i\) 台电脑开始,那么后手一定会让我们取到一个所有经过这个点的区间之和的最小值。所以我们只要让这个最小值最大即可。

对于做法先做一个前缀和,之后用 ST 表记录从这个点开始的长度为 \(\lceil \frac{n}{2}\rceil\) 的区间元素之和,然后枚举每一个电脑 \(i\),能够经过它的区间起始位置在 \([i-\lceil \frac{n}{2}\rceil+1,i]\) 之间。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=1e6+5;
ll n,a[MAXN],f[MAXN];
ll st[MAXN][20],lg[MAXN];
ll query(ll l,ll r){
	ll len=lg[r-l+1];
	return min(st[l][len],st[r-(1<<len)+1][len]);
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>a[i];
		a[n+i]=a[i];
	}
	for(int i=1;i<=2*n;++i){
		f[i]=f[i-1]+a[i];
	}
	ll sa=ceil(n*1.0/2);
	for(int i=2;i<MAXN;++i){
		lg[i]=lg[i>>1]+1;
	}
	for(int i=1;i<=2*n;++i){
		st[i][0]=f[i+sa-1]-f[i-1];
	}
	for(int l=1;l<=lg[2*n];++l){
		for(int i=1;i+(1<<l)-1<=2*n;++i){
			st[i][l]=min(st[i][l-1],st[i+(1<<(l-1))][l-1]);
		}
	}
	ll ans=0;
	for(int i=sa;i<=2*n;++i){
		ans=max(ans,query(i-sa+1,i));
	}
	cout<<ans<<endl;
	return 0;
}
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 10天前 0

暂无评论

推荐阅读
  cA1FqmrigEPj   12天前   36   0   0 算法与数据结构
BLQ4mFeCsIAS