YbtOJ#493-最大分数【斜率优化dp,分治】
正题
题目链接:http://www.ybtoj.com.cn/contest/117/problem/1
题目大意
\(n\)个数的一个序列,给其中的一些数打上标记。
一个标记方案的贡献为\(s_1\)表示有多少对\(L,R\)满足区间\([L,R]\)都被打上了标记,\(s_2\)表示标记的数字和。贡献为\(s_1-s_2\)
\(m\)次询问,修改一个数后,求最大的可能贡献(询问之间相互独立)
\(1\leq n,m\leq 3\times 10^5\)
解题思路
先把答案减去一个\(\sum_{i=1}^na_i\),这样就变为对于一段\([L,R]\)要么选择\(s_1\)要么选择\(s_2\)
先考虑不带修改怎么搞,设\(f_i\)表示前\(i\)个的最大贡献。
定义\(s_i=\sum_{j=1}^ia_i\)然后有方程
\]
这个东西可以斜率优化搞(考场上犯病写了个\(CDQ\),调了我半天)
然后带修改,考虑到每次只会影响一个数字,可以理解为一个前缀和后缀拼起来。把刚刚那个\(dp\)再反过来做一次记为\(g_i\)。
那么现在对于修改的位置\(x\),我们要么选择\(x\),要么跨过\(x\),也就是最大化
\]
前面那个可以把两个前/后缀的max的\(f_j-s_j\)和\(g_i+s_{i-1}\)加起来就好了。
后面那个考虑分治,我们每次分治到一个位置\([l,mid,r]\),如果需要往左走就统计\(i\in[0,l-1]\)和\(j\in[mid+1,r]\)的答案。右边同理。
因为我们的每次的时间复杂度是外面的大小,所以我们可以维护一个前后缀的凸壳,然后在上面二分时间复杂度就是\(O(n\log^2 n)\)的。
同时维护两个凸壳需要回溯所以很麻烦,分开两次正反做一次就好了。
时间复杂度\(O(n\log^2 n)\)
code
(考场代码,有点丑)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;
const ll N=3e5+10,inf=1e18;
ll n,m,ans,lmax,rmax,top,st[N],suf[N];
ll a[N],f[N],g[N],s[N],prt[N],w[N],yf[N];
vector<ll > q[N];
ll px(ll x,ll *f)
{return f[x]*2+x*x-x;}
ll xj(ll x1,ll y1,ll x2,ll y2)
{return x1*y2-x2*y1;}
ll xl(ll a,ll b,ll c,ll *f){
ll y1=px(b,f)-px(a,f),x1=b-a;
ll y2=px(c,f)-px(a,f),x2=c-a;
return xj(x1,y1,x2,y2);
}
ll ck(ll l,ll r,ll *f)
{return f[l]+(r-l+1)*(r-l)/2;}
ll solve(ll l,ll r,ll *f){
if(l==r)return f[l]-s[l];
ll mid=(l+r)>>1;
ll maxs=solve(l,mid,f);top=0;
for(ll i=l;i<=mid;i++){
while(top>1&&xl(st[top-1],st[top],i,f)>=0)top--;
st[++top]=i;
}
for(ll i=mid+1;i<=r;i++){
while(top>1&&ck(st[top],i,f)<ck(st[top-1],i,f))top--;
f[i]=max(f[i],max(ck(st[top],i,f),s[i]+maxs));
}
maxs=max(maxs,solve(mid+1,r,f));
return maxs;
}
ll cw(ll l,ll r)
{return f[l]+g[r]+(r-l-1)*(r-l)/2;}
ll xll(ll a,ll b,ll c){
ll y1=(yf[b]-yf[a])*2,x1=b-a;
ll y2=(yf[c]-yf[a])*2,x2=c-a;
return xj(x1,y1,x2,y2);
}
ll xlr(ll a,ll b,ll c){
ll y1=yf[b]-yf[a],x1=(n-b+1)-(n-a+1);
ll y2=yf[c]-yf[a],x2=(n-c+1)-(n-a+1);
return xj(x1,y1,x2,y2);
}
void calc(ll L,ll R){
if(L==R){
for(ll i=0;i<q[L].size();i++){
ll x=q[L][i],tmp;
prt[x]=max(ans-w[x]+a[L]-s[n],prt[x]);
}
while(top>1&&xll(st[top-1],st[top],L)>=0)top--;
st[++top]=L;
return;
}
ll mid=(L+R)>>1,pa=ans;
if(top){
for(ll i=mid+1;i<=R;i++){
ll l=1,r=top-1;
while(l<=r){
ll x=(l+r)>>1;
if(cw(st[x],i)<=cw(st[x+1],i))l=x+1;
else r=x-1;
}
ans=max(ans,cw(st[l],i));
}
}
calc(L,mid);ans=pa;
calc(mid+1,R);
return;
}
void cblc(ll L,ll R){
if(L==R){
for(ll i=0;i<q[L].size();i++){
ll x=q[L][i],tmp;
prt[x]=max(ans-w[x]+a[L]-s[n],prt[x]);
}
while(top>1&&xlr(st[top-1],st[top],L)>=0)top--;
st[++top]=L;
return;
}
ll mid=(L+R)>>1,pa=ans;
if(top){
for(ll i=L;i<=mid;i++){
ll l=1,r=top-1;
while(l<=r){
ll x=(l+r)>>1;
if(cw(i,st[x])<=cw(i,st[x+1]))l=x+1;
else r=x-1;
}
ans=max(ans,cw(i,st[l]));
}
}
cblc(mid+1,R);ans=pa;
cblc(L,mid);
return;
}
signed main()
{
freopen("score.in","r",stdin);
freopen("score.out","w",stdout);
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[n-i+1]);
for(ll i=1;i<=n;i++)s[i]=s[i-1]+a[i];
solve(0,n,g);
for(ll i=1;i<n-i+1;i++)
swap(a[i],a[n-i+1]),swap(g[i],g[n-i+1]);
for(ll i=1;i<=n;i++)s[i]=s[i-1]+a[i];
solve(0,n,f);
scanf("%lld",&m);
for(ll i=1;i<=m;i++){
ll x;
scanf("%lld%lld",&x,&w[i]);
q[x].push_back(i);
}
suf[n+2]=-inf;
for(ll i=n+1;i>=1;i--)
suf[i]=max(suf[i+1],g[i]+s[i-1]);
for(ll i=0,pre=-inf;i<=n;i++){
for(ll j=0;j<q[i].size();j++){
ll x=q[i][j];
prt[x]=suf[i+1]+pre-s[n];
}
pre=max(pre,f[i]-s[i]);
}
ans=-inf;top=0;
for(ll i=1;i<=n;i++)yf[i]=f[i]*2+i*i+i;calc(0,n+1);
ans=-inf;top=0;
for(ll i=1;i<=n;i++)yf[i]=g[i]*2+(n-i+1)*(n-i+1)+(n-i+1);
cblc(0,n+1);
for(ll i=1;i<=m;i++)
printf("%lld\n",max(prt[i],0ll));
return 0;
}
YbtOJ#493-最大分数【斜率优化dp,分治】的更多相关文章
- bzoj2149拆迁队 斜率优化dp+分治
2149: 拆迁队 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 397 Solved: 177[Submit][Status][Discuss] ...
- 【BZOJ-1492】货币兑换Cash DP + 斜率优化 + CDQ分治
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 3396 Solved: 1434[Submit][Sta ...
- 【uoj#244】[UER #7]短路 CDQ分治+斜率优化dp
题目描述 给出 $(2n+1)\times (2n+1)$ 个点,点 $(i,j)$ 的权值为 $a[max(|i-n-1|,|j-n-1|)]$ ,找一条从 $(1,1)$ 走到 $(2n+1,2n ...
- 【bzoj3672】[Noi2014]购票 斜率优化dp+CDQ分治+树的点分治
题目描述 给出一棵以1为根的带边权有根树,对于每个根节点以外的点$v$,如果它与其某个祖先$a$的距离$d$不超过$l_v$,则可以花费$p_vd+q_v$的代价从$v$到$a$.问从每个点到1花费 ...
- BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)
BZOJ1492:[NOI2007]货币兑换 题目传送门 [问题描述] 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和B纪念券(以下简称B券).每个持有金券的 ...
- 2018.09.29 bzoj3675: [Apio2014]序列分割(斜率优化dp)
传送门 斜率优化dp经典题目. 首先需要证明只要选择的K个断点是相同的,那么得到的答案也是相同的. 根据分治的思想,我们只需要证明有两个断点时成立,就能推出K个断点时成立. 我们设两个断点分成的三段连 ...
- [Noi2014]购票 斜率优化DP+可持久化凸包
貌似网上大部分题解都是CDQ分治+点分治然后再斜率优化DP,我貌似并没有用这个方法. 这一题跟这题有点像,只不过多了一个l的限制 如果说直接跑斜率优化DP,存储整个序列的话,显然是不行的,如图所示(图 ...
- 斜率优化DP学习笔记
先摆上学习的文章: orzzz:斜率优化dp学习 Accept:斜率优化DP 感谢dalao们的讲解,还是十分清晰的 斜率优化$DP$的本质是,通过转移的一些性质,避免枚举地得到最优转移 经典题:HD ...
- 【bzoj3675】[Apio2014]序列分割 斜率优化dp
原文地址:http://www.cnblogs.com/GXZlegend/p/6835179.html 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列 ...
随机推荐
- Socket 网络编程和IO模型
最近做了一个织机数据采集的服务器程序. 结构也非常简单,织机上的嵌入式设备,会通过Tcp 不停的往服务器发送一些即时数据.织机大改有个几十台到几百台不定把 刨去业务,先分析一下网络层的大概情况.每台织 ...
- 消除不受信任的HTML (来防止XSS攻击)
问题 在做网站的时候,经常会提供用户评论的功能.有些不怀好意的用户,会搞一些脚本到评论内容中,而这些脚本可能会破坏整个页面的行为,更严重的是获取一些机要信息,此时需要清理该HTML,以避免跨站脚本cr ...
- GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组
1 drop table orders; 2 create table orders ( 3 o_id int auto_increment primary key, 4 orderdate date ...
- Struts2之国际化
时间:2017-1-11 11:12 --国际化Struts2已经对国际化进行了封装,我们只需要根据其提供的API进行访问即可.要使用国际化的Action必须继承ActionSupport.1.什么是 ...
- 如何让BootStrap栅格之间留出空白间隙呢?
BootStrap栅格之间留出空隙 BootStrap栅格系统可以把我们的container容器划分为若干等分,如果想要每个部分之间留出一定的空隙,我们很可能首先想到的方法就是用margin外边距来使 ...
- spring boot纯注解开发模板
简介 spring boot纯注解开发模板 创建项目 pom.xml导入所需依赖 点击查看源码 <dependencies> <dependency> <groupId& ...
- 剑指 Offer 36. 二叉搜索树与双向链表
剑指 Offer 36. 二叉搜索树与双向链表 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表.要求不能创建任何新的节点,只能调整树中节点指针的指向. 为了让您更好地理解问题,以下面的 ...
- Python中的变量以及变量的命名
1.变量的定义 在 python 中,每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建 等号(=)用来给变量赋值 =左边是一个变量名 =右边是存储在变量中的值 变量名=值 变量定义之后,后续就 ...
- vue post 请求 是 request payload 而不是 FromData ,以及 格式转换成 FromData 需要的 key value 格式
export function 方法名字(传进来要给后端的参数){ return request({ url : ' 后端提供的接口路径 ', method ...
- Python - 面向对象编程 - MRO 方法搜索顺序
为什么会讲 MRO? 在讲多继承的时候:https://www.cnblogs.com/poloyy/p/15224912.html 有讲到, 当继承的多个父类拥有同名属性.方法,子类对象调用该属性. ...