题目

分析

\(s[i]\)表示a前缀和。

设\(f[i]\)表示做完了1~i的友谊颗粒的最优值(不一定选i),那么转移方程为

\[f[i]=max\{f[i-1],max\{f[j]-s[i]+s[j]+\dfrac{(i-j)(i-j+1)}{2}\}\}$$,用斜率优化来处理这个。
类似的,设$g_i$表示做完了i~n的友谊颗粒的最优值(不一定选i),
将a翻转,像f一样做一遍,再将g翻转就可以了。
对于询问(p,x),如果我们不选择p,那么答案就是$f[i-1]+g[i+1]$
如果我们选择了p,我们再设$F[i]$表示,必选i的最优值。
$$F[i]=max\{f[j]+g[k]+\dfrac{(k-j+1)(k-j+2)}{2}\}(j<i<k)\]

时间复杂度是\(O(N^2)\)

如何可以更快的求出\(F[i]\)呢,

分治,假设当前做到\([l,r]\),左端点\([l,mid]\),i和右端点在\([mid+1,r]\)

\(tmp[i]\)表示做完了左端点~i的友谊颗粒,且必选i的最优值

我们将\([l-1,mid-1]\)的端点扔进斜率优化的单调栈,扫一遍\([mid+1,r]\)求出tmp,

\[tmp[i]=max\{f[j]+g[i+1]+\dfrac{(i-j+1)(i-j+2)}{2}\}(j\in{[l-1,mid-1]}<i\in{[mid+1,r]})
\]

那么\(F[i]\)就是当前区间\(tmp[i]\)的后缀max

因为只考虑了i在\([mid+1,r]\)的情况,反过来做一遍就可以了。

那么选择了p的的最优值就是\(F[p]+a[p]-x\)

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <queue>
#include <stack>
using namespace std;
const int maxlongint=2147483647;
const int mo=1e9+7;
const int N=1000005;
#define rev(h) for(int i=1;i<=n/2;i++) swap(h[i],h[n-i+1])
#define val(h,j,k) 1ll*(h[j]-h[k]+s[j]-s[k]-1ll*j*1.0/2+1ll*k*1.0/2+1ll*j*j*1.0/2-1ll*k*k*1.0/2)*1.0/(j-k)
int n,m,t[N],top;
long long a[N],s[N],f[N],g[N],F[N],tmp[N];
void dg(long long *f,long long *g,int l,int r)
{
if(l==r)
{
F[l]=max(F[l],f[l-1]+g[l+1]+1-a[l]);
return;
}
int mid=(l+r)>>1;
top=0;
for(int i=l-1;i<=mid;i++)
{
for(;top>1 && val(f,i,t[top])>=val(f,t[top],t[top-1]);) top--;
t[++top]=i;
}
for(int i=mid+1;i<=r;i++)
{
for(;top>1 && val(f,t[top],t[top-1])<=i;) top--;
int j=t[top];
tmp[i]=f[j]-(s[i]-s[j])+1ll*(i-j)*(i-j+1)/2+g[i+1];
}
for(int i=r-1;i>=mid+1;i--) tmp[i]=max(tmp[i],tmp[i+1]);
for(int i=r;i>=mid+1;i--) F[i]=max(F[i],tmp[i]);
dg(f,g,l,mid),dg(f,g,mid+1,r);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),s[i]=s[i-1]+a[i],F[i]=-a[i]+1;
t[top=1]=0;
for(int i=1;i<=n;i++)
{
for(;top>1 && val(f,t[top],t[top-1])<=i;) top--;
int j=t[top];
f[i]=max(f[j]-(s[i]-s[j])+1ll*(i-j)*(i-j+1)/2,f[i-1]);
for(;top>1 && val(f,i,t[top])>=val(f,t[top],t[top-1]);) top--;
t[++top]=i;
}
rev(a);
t[top=1]=0;
for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
for(int i=1;i<=n;i++)
{
for(;top>1 && val(g,t[top],t[top-1])<=i;) top--;
int j=t[top];
g[i]=max(g[j]-(s[i]-s[j])+1ll*(i-j)*(i-j+1)/2,g[i-1]);
for(;top>1 && val(g,i,t[top])>=val(g,t[top],t[top-1]);) top--;
t[++top]=i;
}
rev(a);
for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
rev(g);
dg(f,g,1,n);
rev(a);
rev(g);
for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
rev(F);
rev(f);
dg(g,f,1,n);
rev(F);
rev(g);
rev(f);
rev(a);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
long long p,x;
scanf("%lld%lld",&p,&x);
printf("%lld\n",max(f[p-1]+g[p+1],F[p]+a[p]-x));
}
}

Atcoder Regular Contest 066 F genocide【JZOJ5451】的更多相关文章

  1. AtCoder Regular Contest 085 C HSI【概率论】

    AtCoder Regular Contest 085 C HSI 没学概率论还不怎么看得懂,虽然感觉不难,其实明明可以猜出来的..... 参考博客:https://www.cnblogs.com/g ...

  2. AtCoder Regular Contest 066 F Contest with Drinks Hard

    题意: 你现在有n个题目可以做,第i个题目需要的时间为t[i],你要选择其中的若干题目去做.不妨令choose[i]表示第i个题目做不做.定义cost=∑(i<=n)∑(i<=j<= ...

  3. AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图

    AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图 链接 AtCoder 大意 在数轴上放上n个点,点i可能的位置有\(x_i\)或者\(y_i\ ...

  4. AtCoder Beginner Contest 137 D题【贪心】

    [题意]一共有N个任务和M天,一个人一天只能做一个任务,做完任务之后可以在这一天之后的(Ai-1)天拿到Bi的工资,问M天内最多可以拿到多少工资. 链接:https://atcoder.jp/cont ...

  5. 【AtCoder Regular Contest 082 F】Sandglass

    [链接]点击打开链接 [题意] 你有一个沙漏. 沙漏里面总共有X单位的沙子. 沙漏分A,B上下两个部分. 沙漏从上半部分漏沙子到下半部分. 每个时间单位漏1单位的沙子. 一开始A部分在上面.然后在r1 ...

  6. 【推导】【模拟】AtCoder Regular Contest 082 F - Sandglass

    题意:有个沙漏,一开始bulb A在上,bulb B在下,A内有a数量的沙子,每一秒会向下掉落1.然后在K个时间点ri,会将沙漏倒置.然后又有m个询问,每次给a一个赋值ai,然后询问你在ti时刻,bu ...

  7. 【arc077f】AtCoder Regular Contest 077 F - SS

    题意 给你一个形如"SS"的串S,以及一个函数\(f(x)\),\(x\)是一个形如"SS"的字符串,\(f(x)\)也是一个形如"SS"的 ...

  8. 【构造】AtCoder Regular Contest 079 F - Namori Grundy

    对每个点的取值都取最小的可能值. 那个图最多一个环,非环的点的取值很容易唯一确定. 对于环上的点v,其最小可能取值要么是mex{c1,c2,...,ck}(ci这些是v直接相连的非环点)(mex是). ...

  9. 【AtCoder Regular Contest 076 F】Exhausted (贪心)

    Description 机房里有M台电脑排成一排,第i台电脑的坐标是正整数i. 现在有N个OIer进入了机房,每个OIer需要一台电脑来学tui习ji,同时每个OIer对自己电脑所处的坐标范围有一个要 ...

随机推荐

  1. webdriervAPI(操作cookie)

    from  selenium  import  webdriver driver  =  webdriver.Chorme() driver.get("http://www.baidu.co ...

  2. python 实现 灰色预测 GM(1,1)模型 灰色系统 预测 灰色预测公式推导

    来源公式推导连接 https://blog.csdn.net/qq_36387683/article/details/88554434 关键词:灰色预测 python 实现 灰色预测 GM(1,1)模 ...

  3. IIS写权限漏洞和XFF刷票原理

    IIS写权限漏洞 PUT写入漏洞 此漏洞主要是因为服务器开启了webdav的组件导致的 1.扫描漏洞,yes,可以PUT: 2.用老兵的工具上传一句话文件test.txt,然后move改名为shell ...

  4. spring boot 框架根據 sql 創建語句自動生成 MVC層類代碼

    GITHUB: https://github.com/lin1270/spring_boot_sql2code 會自動生成model.mapper.service.controller. 代碼使用No ...

  5. json与String的转化

    String转成jsonObject    JsonObject   json = JsonObject.fromObject(String str) String转成JsonArray      J ...

  6. HYSBZ 1797 Mincut 最小割

    Descrption A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站, ...

  7. Java回调实现异步

    在正常的业务中使用同步线程,如果服务器每处理一个请求,就创建一个线程的话,会对服务器的资源造成浪费.因为这些线程可能会浪费时间在等待网络传输,等待数据库连接等其他事情上,真正处理业务逻辑的时间很短很短 ...

  8. k8s 1.9安装

    关闭所有节点的selinux.iptables.firewalld systemctl stop iptables systemctl stop firewalld systemctl disable ...

  9. 剑指offer-数组中只出现一次的数字-数组-python

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.   # -*- coding:utf-8 -*- class Solution: # 返回[a, ...

  10. luogu P5366 [SNOI2017]遗失的答案

    luogu 首先gcd为\(G\),lcm为\(L\),有可能出现的数(指同时是\(G\)的因数以及是\(L\)的倍数)可以发现只有几百个.如果选出的数要能取到gcd,那么对于每种质因子,都要有一个数 ...