[ARC066F]Contest with Drinks Hard

来源:互联网 发布:日语扫描翻译软件 编辑:程序博客网 时间:2024/06/07 00:42

Description

给出一个序列a,你需要求出一个0/1序列c,使得

i=1nj=ink=ijCki=1nCiAi

最大
给出m次修改形如(x,y),表示把a[x]改成y,每次修改之间独立,对于每次修改之后求出答案

n,m<=3*1e5

Solution

首先一次询问可以直接Dp
设Fi表示考虑到i的最大价值,O(n)转移显然
发现转移可以斜率优化,不过这个斜率优化写的是单调栈,自己感受一下
正着做一遍再反着做一遍,接下来我们只需要求出hi表示i必须选的答案
这个东西可以用cdq分治做,为了保证覆盖所有情况要正着做一遍再反着做一遍
注意分治边界的一些奇怪东西

Code

#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long ll;typedef double db;int read() {    char ch;    for(ch=getchar();ch<'0'||ch>'9';ch=getchar());    int x=ch-'0';    for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';    return x;}const int N=3*1e5+5;const ll inf=1e16;int n,m,x,y,a[N],stack[N],top;ll f[N],g[N],h[N],ans[N],t[N],c[N],tmp[N],sum[N];db P(int y,int x) {    return (t[y]+(ll)y*(y-1)/2+sum[y]-t[x]-(ll)x*(x-1)/2-sum[x])*1.0/(y-x);}void Dp() {    fo(i,1,n) sum[i]=sum[i-1]+a[i];stack[top=1]=0;    fo(i,1,n) {        while (top>1&&P(stack[top],stack[top-1])<=i) top--;        int now=stack[top];        t[i]=max(t[i-1],t[now]+(ll)(i-now)*(i-now+1)/2+sum[now]-sum[i]);        while (top>1&&P(stack[top],stack[top-1])<P(i,stack[top])) top--;        stack[++top]=i;    }}void solve(int l,int r) {    if (l==r) {        h[l]=max(h[l],g[r+1]+f[l-1]+1-a[l]);        return;    }    int mid=l+r>>1;    stack[top=1]=l-1;    fo(i,l,mid-1) {        while (top>1&&P(stack[top],stack[top-1])<P(i,stack[top])) top--;        stack[++top]=i;    }    fo(i,mid,r) {        while (top>1&&P(stack[top],stack[top-1])<=i) top--;        int now=stack[top];        tmp[i]=t[now]+(ll)(i-now)*(i-now+1)/2+sum[now]-sum[i]+g[i+1];    }    fd(i,r-1,mid) tmp[i]=max(tmp[i],tmp[i+1]);    fo(i,mid,r) h[i]=max(h[i],tmp[i]);    solve(l,mid);solve(mid+1,r);}int main() {    freopen("genocide.in","r",stdin);    freopen("genocide.out","w",stdout);    n=read();    fo(i,1,n) a[i]=read();    Dp();fo(i,1,n) f[i]=t[i];    fo(i,1,n/2) swap(a[i],a[n-i+1]);    Dp();fo(i,1,n) g[i]=t[n-i+1];    fo(i,1,n) ans[i]=-inf;    fo(i,1,n/2) swap(a[i],a[n-i+1]);    fo(i,1,n) t[i]=f[i];    fo(i,1,n) sum[i]=sum[i-1]+a[i];    fo(i,1,n) h[i]=-inf;    solve(1,n);    fo(i,1,n) ans[i]=max(ans[i],h[i]);    fo(i,1,n) swap(f[i],g[i]);    fo(i,1,n/2) {        swap(a[i],a[n-i+1]);        swap(f[i],f[n-i+1]);        swap(g[i],g[n-i+1]);    }    fo(i,1,n) t[i]=f[i];    fo(i,1,n) sum[i]=sum[i-1]+a[i];    fo(i,1,n) h[i]=-inf;    solve(1,n);    fo(i,1,n) ans[i]=max(ans[i],h[n-i+1]);    fo(i,1,n/2) {        swap(f[i],f[n-i+1]);        swap(g[i],g[n-i+1]);        swap(a[i],a[n-i+1]);    }    fo(i,1,n) swap(f[i],g[i]);    for(m=read();m;m--) x=read(),y=read(),printf("%lld\n",max(f[x-1]+g[x+1],ans[x]+a[x]-y));    return 0;}
原创粉丝点击