SPOJ - UNTITLE1 Untitled Problem II
时间:2021-08-12
本文章向大家介绍SPOJ - UNTITLE1 Untitled Problem II,主要包括SPOJ - UNTITLE1 Untitled Problem II使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目
解法
考虑一次操作 \((0,x,y,k)\) 对前缀和 \(s_i\) 的影响:
\[\Delta =\begin{cases} k\cdot(i-x+1), & x\le i\le y \\k\cdot (y-x+1), & i>y\end{cases}
\]
先给每个下标设定一个 \(c_i\) 表示增加的定值,\(k_i\) 表示增加的 \(i\) 的系数。
那么询问 \((x,y)\) 的答案就是:
\[\text{Ans}=\max_{i=x}^y\{s_i+c_i+k_i\cdot i\}
\]
显然是过不去的。不过事实上可以将区间分块。
- \(s_i\) 还是表示 \(i\) 下标,处理非整块的情况。
- \(c_i,k_i\) 都表示第 \(i\) 个块的值。
问题转化为在长度为 \(B\) 的块内查找上文的 \(\max\)。
将下标 \(i\) 抽象成点 \((i,s_i)\),那么 \(\text{Ans}\) 相当于斜率为 \(-k_{bl_i}\) 的过点 \(i,i\in S_{bl_i}\) 的最大截距。维护一个凸包,然后在凸包上二分斜率即可。当凸包被散块修改时,暴力重构凸包。
接下来计算一下复杂度:
- 修改。\(\mathcal O(m\cdot (B+\frac{n}{B}))\)。
- 查询。处理散块是 \(\mathcal O(mB)\) 的;对于整块,暴力重构单次是 \(\mathcal O(B)\) 的,总共是 \(\mathcal O(mB)\) 的,二分是 \(\mathcal O(m\cdot \frac{n}{B}\cdot \log\sqrt B)\) 的。
所以最优块长应该满足 \(\frac{B^2}{\log \sqrt B}=n\)(但是我没算常数),可能比 \(\sqrt n\) 略大,我直接取了 \(\sqrt n\)。
代码
#include <cstdio>
#define print(x,y) write(x),putchar(y)
template <class T>
inline T read(const T sample) {
T x=0; char s; bool f=0;
while((s=getchar())>'9' or s<'0')
f|=(s=='-');
while(s>='0' and s<='9')
x=(x<<1)+(x<<3)+(s^48),
s=getchar();
return f?-x:x;
}
template <class T>
inline void write(const T x) {
if(x<0) {
putchar('-'),write(-x);
return;
}
if(x>9) write(x/10);
putchar(x%10^48);
}
#include <cmath>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=5e4+500,maxb=230;
int n,m,B,bl[maxn],K,x,y;
int st[maxb][maxb];
ll s[maxn],k[maxn],c[maxn];
void modify(int pos,int l=0,int r=0) {
if(l and r) {
st[pos][0]=0;
ll tmp=1ll*K*(l-x+1);
for(int i=l;i<=r;++i)
s[i]+=tmp,tmp+=K;
}
else k[pos]+=K,c[pos]+=1ll*K*(1-x);
}
ll query(int pos,int l=0,int r=0) {
if(l and r) {
ll tmp=s[l]+k[pos]*l;
for(int i=l+1;i<=r;++i)
tmp=max(tmp,s[i]+k[pos]*i);
return tmp+c[pos];
}
if(!st[pos][0]) {
int *tp=&st[pos][0];
for(int i=(pos-1)*B+1;i<=pos*B;++i) {
while((*tp)>1 and 1ll*(s[i]-s[st[pos][*tp]])*(st[pos][*tp]-st[pos][*tp-1])>1ll*(s[st[pos][*tp]]-s[st[pos][*tp-1]])*(i-st[pos][*tp]))
--(*tp);
st[pos][++(*tp)]=i;
}
}
l=1,r=st[pos][0]-1; int mid,a,b;
while(l<=r) {
mid=l+r>>1;
a=st[pos][mid];
b=st[pos][mid+1];
if(s[b]-s[a]>-k[pos]*(b-a))
l=mid+1;
else r=mid-1;
}
return s[st[pos][l]]+c[pos]+k[pos]*st[pos][l];
}
signed main() {
n=read(9); B=sqrt(n);
for(int i=1;i<=n;++i)
s[i]=s[i-1]+read(9),
bl[i]=(i-1)/B+1;
m=read(9);
int op; ll ans;
while(m--) {
op=read(9),x=read(9);
y=read(9);
if(!op) {
K=read(9);
if(bl[x]^bl[y]) {
modify(bl[x],x,bl[x]*B);
modify(bl[y],(bl[y]-1)*B+1,y);
for(int i=bl[x]+1;i<bl[y];++i)
modify(i);
}
else modify(bl[x],x,y);
K*=(y-x+1);
for(int i=y+1;i<=bl[y]*B;++i)
s[i]+=K;
for(int i=bl[y]+1;i<=bl[n];++i)
c[i]+=K;
}
else {
ans=0;
if(bl[x]^bl[y]) {
ans=query(bl[x],x,bl[x]*B);
ans=max(ans,query(bl[y],(bl[y]-1)*B+1,y));
for(int i=bl[x]+1;i<bl[y];++i)
ans=max(ans,query(i));
}
else ans=query(bl[x],x,y);
print(ans,'\n');
}
}
return 0;
}
原文地址:https://www.cnblogs.com/AWhiteWall/p/12747997.html
- 破解之美:利用ECB加密缺陷突破cookie加密
- 让Python猜猜你是否能约会成功
- python学习笔记之初识Python
- 从APK解密到批量获取他人信息
- React native和原生之间的通信
- 移动云存储服务平台Parse下的iOS安全分析
- 经典算法学习之回溯法
- 渗透测试系统BackBox Linux 4.1发布
- CMS漏洞检测工具 - CMSmap
- 基因组分析中多物种同源基因的鉴定和筛选
- SpringMVC类型转换器、属性编辑器PropertiesEditor源码分析CustomDateEditor源码分析TypeConverterDelegate源码分析
- Intellij IDEA 插件开发之自建插件仓库
- 空Word文档附件:绕过垃圾邮件过滤的新方法
- SpringMVC基本使用关于DisptacherServlet关于ServletContainerInitializer最简单配置接收参数路径变量表单变量
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法