SP2940题解
啃论文的时候论文里面的题。
题意:
- 区间加
- 询问区间前缀和之和的最值。
我们先弱化一下问题:将“区间”二字去掉。
我们思考一下一个点可能成为答案的条件。假设现在总共进行的区间加操作令整个序列加上了 \(k\),那么 \(i\) 比 \(j\) 厉害的条件就是:
\]
\]
\]
\]
注意到这里类似斜率,相当于将位置 $ i $ 看做一个点 $ (i,s_i) $ 后对整个序列建立凸壳,每次查询时在凸壳上二分。
回到原问题上,我们只需要维护出整个区间的凸壳即可。
但是维护整个区间的凸壳过于困难,考虑分块,将整个区间拆成几个散块和一堆块,对大块维护凸壳,散块直接暴力。
区间加只需要大块打标记,散块重构凸包即可。
设块长为 \(B\)。复杂度是 \(O(n\log n+m(\frac n B\log n+B)+m(\frac n B+B)\),取 \(B=\sqrt {n\log n}\) 即可得到复杂度 \(O(n\log n+m\sqrt {n\log n})\)。
但是不知道为什么取 \(B=\sqrt n\) 跑得更快。。。
#include<iostream>
#include<cctype>
#include<cmath>
typedef long long ll;
const int M=50005,B=225;
int n,m,p,L[M/B+5],R[M/B+5],id[M],pos[M];ll S[M/B+5];char X[1<<24|1],Y[1<<24|1],*p1=X,*p2=Y;
inline ll max(const ll&a,const ll&b){
return a>b?a:b;
}
struct Block{
int n,len,tag,a[B+5],id[B+5];ll s[B+5];
inline void Update(){
for(int i(1);i<=n;++i)a[i]+=tag,s[i]=s[i-1]+a[i];s[n+1]=-1e18/2;tag=0;
}
inline ll Query(){
int L(1),R(len),mid,ans(0);
while(L<=R){
mid=L+R>>1;
if(s[id[mid]]+id[mid]*tag<=s[id[mid+1]]+id[mid+1]*tag)L=mid+1,ans=mid;
else R=mid-1;
}
return s[id[ans+1]]+1ll*id[ans+1]*tag;
}
inline void Build(){
Update();len=0;
for(int i=1;i<=n;++i){
while(len>1&&(s[i]-s[id[len]])*(id[len]-id[len-1])>=(s[id[len]]-s[id[len-1]])*(i-id[len]))--len;
id[++len]=i;
}
id[len+1]=n+1;
}
}block[M/B+5];
inline void update(){
for(int i=1;(i-1)*p<n;++i)S[i]=S[i-1]+block[i].s[id[R[i]]]+1ll*id[R[i]]*block[i].tag;
}
inline void Modify(const int&l,const int&r,const int&x){
const int&q=pos[l],&p=pos[r];int i;
if(q==p){
for(i=l;i<=r;++i)block[q].a[id[i]]+=x;block[q].Update();block[q].Build();
}
else{
for(i=q+1;i<=p-1;++i)block[i].tag+=x;
for(i=l;i<=R[pos[l]];++i)block[q].a[id[i]]+=x;block[q].Update();block[q].Build();
for(i=L[pos[r]];i<=r;++i)block[p].a[id[i]]+=x;block[p].Update();block[p].Build();
}
update();
}
inline ll Query(const int&l,const int&r){
const int&q=pos[l],&p=pos[r];int i;ll ans(-1e18/2);
if(q==p){
for(i=l;i<=r;++i)ans=max(ans,S[q-1]+block[q].s[id[i]]+id[i]*block[q].tag);
}
else{
for(i=q+1;i<=p-1;++i)ans=max(ans,block[i].Query()+S[i-1]);
for(i=l;i<=R[pos[l]];++i)ans=max(ans,S[q-1]+block[q].s[id[i]]+id[i]*block[q].tag);
for(i=L[pos[r]];i<=r;++i)ans=max(ans,S[p-1]+block[p].s[id[i]]+id[i]*block[p].tag);
}
return ans;
}
inline int read(){
int n(0);bool typ(false);char s;
while(!isdigit(s=*p1++))typ|=s==45;while(n=n*10+(s&15),isdigit(s=*p1++));return typ?-n:n;
}
inline void write(ll n){
static char s[18];int top(0);if(n<0)*p2++=45,n=-n;
while(s[++top]=n%10^48,n/=10);while(*p2++=s[top--],top);
}
signed main(){
std::cin.read(X,sizeof X);
int i,x,l,r,opt;p=sqrt(n=read());for(i=1;(i-1)*p<n;++i)L[i]=(i-1)*p+1,R[i]=i*p;
for(i=1;i<=n;++i)pos[i]=(i-1)/p+1,block[pos[i]].a[id[i]=i-L[pos[i]]+1]=read();R[pos[n]]=n;
for(i=1;(i-1)*p<n;++i)block[i].n=R[i]-L[i]+1,block[i].Update(),block[i].Build();update();
m=read();while(m--)opt=read(),l=read(),r=read(),opt?write(Query(l,r)),void(*p2++=10):Modify(l,r,read());
std::cout.write(Y,p2-Y);
}
SP2940题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
随机推荐
- Docker的数据管理、网络通信和dockerfile
Docker的数据管理.网络通信和dockerfile 目录 Docker的数据管理.网络通信和dockerfile 一.Docker的数据管理 1. 数据卷 1.1 数据卷定义 1.2 数据卷配置 ...
- docker基础——5.Dockerfile
把应用部署在容器中,改变了用文本文件保存配置信息的方式.而通过传环境变量配置. Dockerfile是一个文本文件,包括容器的指令.按顺序从上到下执行,第一行非注释指令必须是FROM指定基础镜像. D ...
- Redis 学习笔记(六)Redis 如何实现消息队列
一.消息队列 消息队列(Messeage Queue,MQ)是在分布式系统架构中常用的一种中间件技术,从字面表述看,是一个存储消息的队列,所以它一般用于给 MQ 中间的两个组件提供通信服务. 1.1 ...
- asp.core 同时兼容JWT身份验证和Cookies 身份验证两种模式
在实际使用中,可能会遇到,aspi接口验证和view页面的登录验证情况.asp.core 同样支持两种兼容. 首先在startup.cs 启用身份验证. var secrityKey = new Sy ...
- 拔掉网线后, 原本的 TCP 连接还存在吗?
大家好,我是小林. 今天,聊一个有趣的问题:拔掉网线几秒,再插回去,原本的 TCP 连接还存在吗? 可能有的同学会说,网线都被拔掉了,那说明物理层被断开了,那在上层的传输层理应也会断开,所以原本的 T ...
- 字符编码和Python代码操作文件
字符编码和Python代码操作文件 读写模式之a模式 # a模式 只追加模式 # 路径不存在:自动创建 with open(r'a.txt','a',encoding='utf8') as f: pa ...
- 使用 shell 脚本清理内存 buff/cache
#!/bin/bash printf "\e[0;32m数据写入硬盘中,请稍等\e[0m\n" #写入硬盘,防止数据丢失 sync;sync;sync printf "\ ...
- 超简单集成华为 HMS MLKit 机器学习服务:银行卡识别 SDK,一键实现银行卡绑定
前言 小编前面几期文章分别给大家介绍了使用 HMS ML Kit SDK 实现微笑抓拍.证件照 DIY.拍照翻译的功能开发(链接见文章末尾),本次小编给大家带来的是使用 HMS 机器学习服务(ML K ...
- vscode打开多个文件
vscode短时间内打开多个文件会覆盖原先打开的文件,在右方编辑区只显示一个.若想每次打开,都新创建一个编辑,可以用以下2个简单的方法: 方法一:直接在右侧打开的文件上,Ctrl + S,保存一次,再 ...
- NET命令入侵实例
实验目的 了解NET入侵的过程 掌握NET命令的使用方法和它的参数搭配 实验内容 NET命令的使用方法和它的参数搭配 实验环境描述 XP作为客户端,Windows server 2003作为远程服务器 ...