Cenocide
Description
给出一个长度为
n
的序列
接下来有
对于每个道具,询问仅使用这个道具的情况下,最大的总收益为多少。
Data Constraint
Solution
考虑
m
=
预处理出
a
的前缀和序列
设
fi
表示
1
~
若由
j
转移到
用一个单调栈维护斜率单调递减即可。
由于第
i
个数可以不选择,因而
现在考虑
m
<=
同样的,我们设
gj
表示
j
~
对于每一个
Pi
,若不选择这一个数,那么答案显然为
fPi−1
+
gPi+1
。
设
hi
表示必须选择
i
时整个序列的最大收益,那么选择
现在考虑如何求出
h
。
对于一个
令F_i=
则
hx
=
max
(
Fi
+
Gj
-
i∗j
)(
i
<
考虑分治,对于分治区间(
设
那现在考虑如何求出
仔细观察便能发现这样做并不能让所有的情况更新到
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,j,l) for(int i=j;i<=l;i++)
#define fd(i,j,l) for(int i=j;i>=l;i--)
using namespace std;
typedef long long ll;
typedef double db;
const ll N=66e4,maxn=1e12;
ll a[N],b[N],f[N],g[N],h[N],t[N],dd[N];
int top,n,m,j,k,l,i,c;
ll F[N],G[N],d[N],bb;
double xl(ll a,ll b)
{return (F[a]-F[b])/(a-b*1.0);}
double xx(ll a,ll b)
{return (G[a]-G[b])/(a-b*1.0);}
ll max(ll a,ll b)
{return a>b?a:b;}
void ef(int l,int r,int f)
{
if(l==r)return;
int k=0,mid=(l+r)/2;
fo(i,mid+1,r){
while(k-1&&xx(d[k],i)>=xx(d[k-1],d[k]))k--;
d[++k]=i;
}
t[l-1]=-maxn;
fo(i,l,mid){
while(k-1&&xx(d[k-1],d[k])<=i)k--;
t[i]=max(t[i-1],F[i]+G[d[k]]-i*d[k]);
}
if(f==0)fo(i,l,mid)h[i]=max(h[i],t[i-1]);
else fo(i,l,mid)h[n-i+1]=max(h[n-i+1],t[i-1]);
ef(l,mid,f); ef(mid+1,r,f);
}
int main()
{
cin>>n;
fo(i,1,n)scanf("%lld",&a[i]),b[i]=b[i-1]+a[i];
int t;
d[t=1]=0;
fo(i,1,n){
while(t-1&&xl(d[t-1],d[t])<i)t--;
f[i]=max(f[i-1],f[d[t]]+(ll)(i-d[t])*(i-d[t]+1)/2-b[i]+b[d[t]]);
F[i]=f[i]+(ll)(i-1)*(ll)i/2+b[i];
while(t-1&&xl(d[t],i)>=xl(d[t-1],d[t]))t--;
d[++t]=i;
}
d[t=1]=0;
fo(i,1,n)b[i]=b[i-1]+a[n-i+1];
fo(i,1,n){
while(t-1&&xl(d[t-1],d[t])<=i)t--;
g[i]=max(g[i-1],g[d[t]]+(ll)(i-d[t])*(i-d[t]+1)/2-b[i]+b[d[t]]);
F[i]=g[i]+(ll)(i-1)*(ll)i/2+b[i];
while(t-1&&xl(d[t],i)>=xl(d[t-1],d[t]))t--;
d[++t]=i;
}
fo(i,1,n/2)swap(g[i],g[n-i+1]);
fo(i,1,n+1)dd[i]=f[i-1]+g[i+1],b[i]=b[i-1]+a[i];
fo(i,0,n+1)F[i]=f[i]+(ll)i*(i+1)/2+b[i],G[i]=g[i]+(ll)i*(i-1)/2-b[i-1];
fo(i,1,n)h[i]=-maxn;
ef(0,n+1,0);
fo(i,1,n+1)swap(f[i],g[i]),b[i]=b[i-1]+a[n-i+1];
fo(i,1,n/2)swap(f[i],f[n-i+1]),swap(g[i],g[n-i+1]);
fo(i,0,n+1)F[i]=f[i]+(ll)i*(i+1)/2+b[i],G[i]=g[i]+(ll)i*(i-1)/2-b[i-1];
ef(0,n+1,1);
cin>>m;
fo(i,1,m){
scanf("%d%lld",&c,&bb);
ll ans=max(dd[c],h[c]-(bb-a[c]));
printf("%lld\n",ans);
}
}