【Luogu2496】【BZOJ3005】[SDOI2012]体育课
把自己去年在luogu写的一个题解搬过来
1. 题目大意
给定一个长度为 \(n\) 的数列 \(a_1,a_2,a_3,...,a_n\) , 并给出 \(m\) 个操作,操作类型如下:
操作1:查询区间最大值,输出最大值与 \(a_1\) 的差;
操作2:交换两个数的位置;
操作3:选择一段区间 \([l,r]\) 并给定 \(t\) ,将区间中第 \(x\) 个数加上 $x\cdot t $ .
\(n,m \le 10^5\) .
2. 解题报告
本题的正解是分块。
首先我们先考虑操作3,对于两边的元素,我们直接暴力修改然后重构即可。那么我们如何维护整块呢?
维护 \(add[ x ]\) 表示第 \(x\) 块累加的 \(t\) , 那我们要得到单个元素,再维护一个偏移量 \(del[x]\) ,这样块中元素的权值即可表示为 \(w[i]=a[i]+add[x]\times i-del[x]\).
(举个例子,若给块 \([4,6]\) 加上 \(2T, 3T, 4T\) ,那么\(add[x]=T\) ,\(del[x]=2T\),这样 \(w[5]=a[5]+5T-2T=a[5]+3T\) .)
对于操作2,我们直接暴力交换然后重构块即可。
对于操作1,我们考虑在整块被修改后,如何维护块内的最大值。由于每个元素的编号 \(i\) 和权值 \(a_i\) 都是定值且 \(i\) 单增,我们可以将每个元素看成 \((i,a_i)\) ,然后用单调栈维护一个上凸壳。这样随着 \(add\) 的增大,最大元素位置一定向右移动,且元素权值呈单峰。
每个操作维护(询问)的复杂度都为 \(O( n\sqrt{n} )\),再加上本题时间限制宽松,可以轻松通过。
3. 参考程序
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
namespace io {
const int SIZE=(1<<21)+1;
char ibuf[SIZE],*iS,*iT;
char gc()
{
if(iS==iT) iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin);
if(iS==iT) return EOF;
return *iS++;
}
inline int gi()
{
char c; int x=0,f=1;
for(;c<'0'||c>'9';c=gc())if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+c-'0';
return x*f;
}
}
using io::gi;
const int N=100005,qN=320;
int n,m,bel[N],b,s[qN][qN],tp[qN],pos[qN];
ll h[N],a[N],add[qN],del[qN];
#define top s[x][tp[x]]
#define dtp s[x][tp[x]-1]
#define Max(x) s[x][pos[x]]
void remove(int x)
{
for(int i=(x-1)*b+1;i<=x*b;i++) a[i]+=add[x]*i-del[x];
add[x]=del[x]=pos[x]=tp[x]=0;
}
void build(int x)
{
memset(s[x],0,sizeof(s[x]));
for(int i=(x-1)*b+1;i<=x*b;i++)
{
while(tp[x]>1&&(a[i]-a[top])*(top-dtp)>=(a[top]-a[dtp])*(i-top))--tp[x];
s[x][++tp[x]]=i;
}
for(pos[x]=1;pos[x]<=tp[x]&&a[s[x][pos[x]+1]]>=a[s[x][pos[x]]];pos[x]++);
}
void update(int x)
{
for(;pos[x]<=tp[x];pos[x]++)
if(a[s[x][pos[x]+1]]+add[x]*s[x][pos[x]+1]<a[s[x][pos[x]]]+add[x]*s[x][pos[x]])
break;
}
int main()
{
n=gi(),m=gi();
b=sqrt(n);
for(int i=1;i<=n;i++) bel[i]=(i-1)/b+1,a[i]=gi();
for(int i=1;i<=bel[n];i++) build(i);
while(m--)
{
int op=gi(),l=gi(),r=gi();
if(op==1)
{
ll k=a[1]+add[1]-del[1];
ll mx=k;
for(;bel[l]==bel[l-1]&&l<=r;l++)
mx=max(mx,a[l]+add[bel[l]]*l-del[bel[l]]);
for(;l+b<=r;l+=b)
mx=max(mx,a[Max(bel[l])]+add[bel[l]]*Max(bel[l])-del[bel[l]]);
for(;l<=r;l++)
mx=max(mx,a[l]+add[bel[l]]*l-del[bel[l]]);
printf("%lld\n",mx-k);
}
if(op==2)
{
remove(bel[l]),remove(bel[r]);
swap(a[l],a[r]);
build(bel[l]); build(bel[r]);
}
if(op==3)
{
int t=gi(),tl=l;
for(;bel[l]==bel[l-1]&&l<=r;l++) a[l]+=(l-tl+1)*t;
remove(bel[l-1]); build(bel[l-1]);
for(;l+b<=r;l+=b) add[bel[l]]+=t,del[bel[l]]+=(tl-1)*t,update(bel[l]);
for(;l<=r;l++) a[l]+=(l-tl+1)*t;
remove(bel[r]); build(bel[r]);
}
}
}
4. 附:维护上凸壳的正确性数学证明
附赠给不能理解维护上凸壳正确性的同学:
假设现在有3个元素 \(x,y,z\) ,设它们的编号分别为 \(h_x, h_y, h_z\),元素大小为 \(a_x,a_y,a_z\) ,权值为\(w_x,w_y,w_z\) , \(h_x<h_y<h_z\) 。设 \(add\) 值为 \(T\), 若存在 \(T\) 使得 \(w_y > w_x\) 且 \(w_y>w_z\),则作差列出不等式:
\(a_x-a_y<(h_y-h_x)T\) , \(a_y-a_z>(h_z-h_y)T\) .
两式整理合并可得 \(\displaystyle \frac{a_z-a_y}{h_z-h_y}<\frac{a_y-a_x}{h_y-h_x}\) .
即:直线 \(y\to z\) 的斜率小于直线 \(x\to y\) 的斜率,故维护上凸壳。同时易发现,随着 \(T\) 的不断增大,最大元素的位置右移,且最大元素左边的权值递增,右边的权值递减(即单峰)。
【Luogu2496】【BZOJ3005】[SDOI2012]体育课的更多相关文章
- P2496 [SDOI2012]体育课
传送门 分块 对每个块维护一个 $add$ 和 $del$ 标记,对于块 $o$ 内某个位置 $i$,它真实的修改量为 $a[i]+add[o]*i-del[o]$ 这样就可以维护一个区间加一个等差数 ...
- BZOJ 2705: [SDOI2012]Longge的问题 [欧拉函数]
2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 2553 Solved: 1565[Submit][ ...
- BZOJ 2705: [SDOI2012]Longge的问题
2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 2554 Solved: 1566[Submit][ ...
- 【BZOJ】【2705】【SDOI2012】Longge的问题
欧拉函数/狄利克雷卷积/积性函数 2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1275 Solv ...
- BZOJ 2705: [SDOI2012]Longge的问题 GCD
2705: [SDOI2012]Longge的问题 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnl ...
- bzoj 2706: [SDOI2012]棋盘覆盖 Dancing Link
2706: [SDOI2012]棋盘覆盖 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 255 Solved: 77[Submit][Status] ...
- bzoj 2705: [SDOI2012]Longge的问题 歐拉函數
2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1035 Solved: 669[Submit][S ...
- Bzoj 2705: [SDOI2012]Longge的问题 欧拉函数,数论
2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1959 Solved: 1229[Submit][ ...
- BZOJ 2726: [SDOI2012]任务安排( dp + cdq分治 )
考虑每批任务对后面任务都有贡献, dp(i) = min( dp(j) + F(i) * (T(i) - T(j) + S) ) (i < j <= N) F, T均为后缀和. 与j有关 ...
随机推荐
- SprintBoot学习(一)
Spring Boot是什么? 1. SpringBoot是一个框架,一种全新的编程规范,他的产生简化了框架的使用,所谓简化是指简化了Spring众多框架中所需的大量且繁琐的配置文件,所以 Sprin ...
- 吴裕雄 python 神经网络——TensorFlow训练神经网络:花瓣识别
import os import glob import os.path import numpy as np import tensorflow as tf from tensorflow.pyth ...
- Flexconnect部署
该记录主要用于针对于无线网络中Flexconnect的部署,可能涉及到的有Flexconnect中的组件,如何部署.(注意:在7.2版本以前,Flexconnect叫做HREAP),目前都称作为Fle ...
- Fiddler一次性发多个请求
Fiddler一次发送多个请求 选中某个请求: 选中 : Raw, 将request数据拷出: 包含请求header和request body 替换request header里面的ASP.NET_S ...
- LeetCode中等题(三)
题目一: 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明:1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL, m ...
- Session服务器之Session复制!
全部运行在Tomcat下 第一台主机:192.168.200.131 安装nginx 修改hosts文件 [root@localhost ~]# vim /etc/hosts 192.168.200 ...
- 第四节:Vuejs组件及组件之间的交互
一. 组件及其交互 1.组件的注册 (1).全局注册 Vue.component('组件名称', { }) 第1个参数是标签名称,第2个参数是一个选项对象. 选项参数包括 data:必须是一个func ...
- centos 默认php 版本太低移到高版本的办法
// centos 默认有php 版本太低转移到高版本的解决办法 php -v 版本低 ln -s /usr/local/php/bin/php /usr/bin/php
- 为PHP开发搭建环境
为了能在自己的电脑上(mac OS系统)开始编写PHP代码并完成运行,需要有: 1.安装Web服务器 2.安装PHP 3.安装数据库,比如MySQL 4.一个PHP的IDE 为了上面所提到的1~3步的 ...
- 吴裕雄--天生自然PythonDjangoWeb企业开发:学员管理系统后台
需求 提供一个学员管理系统,一个前台页面,展示现有学员,并供新学员提交申请,一个后台,能够处理申请. pip install django==1.11.2 创建项目 使用控制台进入到一个目录下,具体是 ...