专栏文章

题解:P11333 [NOISG2020 Finals] Discharging

P11333题解参与者 2已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@miqmcpll
此快照首次捕获于
2025/12/04 07:09
3 个月前
此快照最后确认于
2025/12/04 07:09
3 个月前
查看原文

Solution

考虑如果某一段 [l,r][l,r] 的最大值为 aka_k,则必定有 ar+1>ka_{r+1} > k,否则 rr+1r \leftarrow r+1 肯定更优。
因此我们只考虑前缀最大值之间的转移,可以令 aimax1jiaja_i \leftarrow \max_{1 \le j \le i} a_j,答案不变。
这样就有
dpi=maxj<idpj+(nj)aidp_i = \max_{j < i} dp_j + (n-j) a_i
显然可以斜率优化。
CPP
#include<bits/stdc++.h>
#define int long long
#define _ ((__int128)1)
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=1e6+10;
int n,a[MAXN],dp[MAXN],tot,pos=1;
struct Node {int x,y;}st[MAXN];
void insert(int x,int y) {
	while(tot>1&&_*(y-st[tot].y)*(st[tot].x-st[tot-1].x)<_*(st[tot].y-st[tot-1].y)*(x-st[tot].x)) tot--;
	return st[++tot]={x,y},void();	
}
signed main() {
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>n;
	ffor(i,1,n) cin>>a[i];
	ffor(i,1,n) a[i]=max(a[i],a[i-1]);
	insert(0,0);
	ffor(i,1,n) {
		while(pos<tot&&_*a[i]*(st[pos+1].x-st[pos].x)>st[pos+1].y-st[pos].y) pos++;
		while(pos>1&&_*a[i]*(st[pos].x-st[pos-1].x)<st[pos].y-st[pos-1].y) pos--;
		dp[i]=n*a[i]+st[pos].y-st[pos].x*a[i];
		insert(i,dp[i]),pos=min(pos,tot);
	}
	cout<<dp[n];
	return 0;
}

评论

2 条评论,欢迎与作者交流。

正在加载评论...