当前位置: 首页 > news >正文

[ARC066F]Contest with Drinks Hard

题意:给定$t_{1\cdots n}$,你要确定一个$01$数组$c_{1\cdots n}$使得$\left(\sum\limits_{1\leq i\leq j\leq n}\prod\limits_{k=i}^jc_k\right)-\sum\limits_{i=1}^nc_it_i$最大,现在有$m$次询问,形如“假如把$t_p$改为$x$,答案是多少?”

相当于选择一些互不相邻的区间,每个长度为$k$的区间有$\frac{k(k+1)}2$的贡献,一个位置$i$被选中则要付出$t_i$的代价

首先看没有询问怎么做,设$f_i$表示前$i$位的答案,$s$为$t$的前缀和,则$f_i=\max\left(f_{i-1},\max\limits_{0\leq j\lt i}f_j+\frac{(i-j)(i-j+1)}2-(s_i-s_j)\right)$

把后面的$\max$里的式子拆开:$\left(-ji+f_j+\frac{j^2-j}2+s_j\right)+\frac{i^2+i}2-s_i$,如果固定$j$,那么括号里是关于$i$的一次函数,整个DP的过程相当于不断地加直线和询问所有直线在$x=i$处的最大值,因为加入的直线斜率越来越小,询问的$x$越来越大,所以用栈维护直线形成的下凸壳即可

现在考虑有询问怎么做,如果一个方案选择的区间不包含$p$,那么问题可以拆成在$[1,p-1],[p+1,n]$中的子问题,把上面的DP正反各做一次得到正的$f_i$和反的$g_i$,这一部分的答案就是$f_{p-1}+g_{p+1}$

如果一个方案选择的区间包含$p$,我们想要求出$h_i$表示选择的某个区间包含$i$的最大答案

最朴素的想法是枚举每一个区间$[l,r]$,用$f_{l-1}+g_{r+1}+\frac{(r-l+1)(r-l+2)}2-\sum\limits_{i=l}^rt_i$更新$h_{l\cdots r}$,这样做太慢,考虑分治

假设当前分治区间为$[l,r]$,我们想要算出所有跨越$[mid,mid+1]$的区间对答案的贡献

枚举右端点$i\in[mid+1,r]$并用$g_{i+1}+\max\limits_{l-1\leq j\lt mid}f_j+\frac{(i-j)(i-j+1)}2-(s_i-s_j)$更新$h_{mid+1\cdots i}$,枚举左端点的左边$i\in[l-1,mid-1]$并用$f_i+\max\limits_{mid\lt j\leq r}g_{j+1}+\frac{(j-i)(j-i+1)}2-(s_j-s_i)$更新$h_{i+1\cdots mid}$,这两个DP可以用和前面一样的方法来完成(先加完直线再单调地查询最大值)

预处理完$f,g,h$后,答案就是$\max(f_{p-1}+g_{p+1},h_p+t_p-x)$

总时间复杂度$O(n\log n)$

#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double du;
const ll inf=9223372036854775807ll;
struct line{
	ll k,b;//y=kx+b
	line(ll k=0,ll b=0):k(k),b(b){}
	ll get(ll x){return k*x+b;}
}st[300010],u;
int tp;
du its(line a,line b){
	return(b.b-a.b)/du(a.k-b.k);
}
int t[300010],n;
ll s[300010],f[300010],g[300010];
void dp(ll*f){
	int i;
	for(i=1;i<=n;i++)s[i]=s[i-1]+t[i];
	tp=1;
	st[1]=line(0,0);
	for(i=1;i<=n;i++){
		while(tp>1&&st[tp].get(i)<=st[tp-1].get(i))tp--;
		f[i]=max(st[tp].get(i)+((ll)i*i+i)/2-s[i],f[i-1]);
		u=line(-i,f[i]+((ll)i*i-i)/2+s[i]);
		while(tp>1&&its(u,st[tp-1])>=its(st[tp],st[tp-1]))tp--;
		st[++tp]=u;
	}
}
ll h[300010];
void solve(int l,int r){
	if(l==r){
		h[l]=1ll-t[l];
		return;
	}
	int mid,i,now;
	ll mx;
	mid=(l+r)>>1;
	solve(l,mid);
	solve(mid+1,r);
	tp=0;
	for(i=l-1;i<mid;i++){
		u=line(-i,f[i]+((ll)i*i-i)/2+s[i]);
		while(tp>1&&its(u,st[tp-1])>=its(st[tp],st[tp-1]))tp--;
		st[++tp]=u;
	}
	now=1;
	mx=-inf;
	for(i=r;i>mid;i--){
		while(now<tp&&its(st[now],st[now+1])>=i)now++;
		mx=max(mx,st[now].get(i)+((ll)i*i+i)/2-s[i]+g[i+1]);
		h[i]=max(h[i],mx);
	}
	tp=0;
	for(i=mid+1;i<=r;i++){
		u=line(-i,g[i+1]+((ll)i*i+i)/2-s[i]);
		while(tp>1&&its(u,st[tp-1])>=its(st[tp],st[tp-1]))tp--;
		st[++tp]=u;
	}
	now=tp;
	mx=-inf;
	for(i=l-1;i<mid;i++){
		while(now>1&&its(st[now],st[now-1])<=i)now--;
		mx=max(mx,st[now].get(i)+((ll)i*i-i)/2+s[i]+f[i]);
		h[i+1]=max(h[i+1],mx);
	}
}
int main(){
	int i,m,x,y;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",t+i);
	dp(f);
	reverse(t+1,t+n+1);
	dp(g);
	reverse(t+1,t+n+1);
	reverse(g+1,g+n+1);
	for(i=1;i<=n;i++)s[i]=s[i-1]+t[i];
	solve(1,n);
	scanf("%d",&m);
	while(m--){
		scanf("%d%d",&x,&y);
		printf("%lld\n",max(f[x-1]+g[x+1],h[x]+t[x]-y));
	}
}

转载于:https://www.cnblogs.com/jefflyy/p/9858865.html

相关文章:

  • 5.0中redis-cli的集群管理测试
  • linux基础学习【10】
  • 北京博派通达科技有限公司(前端面试题) 给需要的人
  • IT界提问的艺术
  • hadoop生态搭建(3节点)-15.Nginx_Keepalived_Tomcat配置
  • Hadoop在安装snappy过程中的问题
  • localStorage和sessionStorage
  • 驻波比
  • 【Python】多进程#181101
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • java 运算符,流程控制语句,键盘录入
  • 【转】在Win7的IIS上搭建FTP服务及用户授权
  • layui-学习02-全局样式
  • Mac OS 系统占用储存空间太大怎么办?
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Angularjs之国际化
  • go语言学习初探(一)
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • unity如何实现一个固定宽度的orthagraphic相机
  • 彻底搞懂浏览器Event-loop
  • 对超线程几个不同角度的解释
  • 分类模型——Logistics Regression
  • 如何进阶一名有竞争力的程序员?
  • 试着探索高并发下的系统架构面貌
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • #在 README.md 中生成项目目录结构
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (pojstep1.3.1)1017(构造法模拟)
  • (分享)自己整理的一些简单awk实用语句
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (蓝桥杯每日一题)love
  • (十三)Flask之特殊装饰器详解
  • (十五)使用Nexus创建Maven私服
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (学习日记)2024.02.29:UCOSIII第二节
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • .NET Framework 4.6.2改进了WPF和安全性
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET 解决重复提交问题
  • .NET 依赖注入和配置系统
  • .Net 知识杂记
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .NET委托:一个关于C#的睡前故事
  • .project文件
  • @SentinelResource详解