P2496 [SDOI2012]体育课
分块
对每个块维护一个 $add$ 和 $del$ 标记,对于块 $o$ 内某个位置 $i$,它真实的修改量为 $a[i]+add[o]*i-del[o]$
这样就可以维护一个区间加一个等差数列的操作了
对于操作 $2$,交换两个位置,直接把两个位置的块标记下传,然后直接交换
对于操作 $1$,考虑到相同的块内 $add$ 只会越来越大,对于某个位置 $i$,它一开始是最大的位置,随着标记的增加,比它大的位置显然一定在它右边
所以考虑维护一个数列,使得数列相邻两个位置中,一旦左边的被超越,下一个可能的最大值就是右边下一个
我一开始天真地以为直接维护一个单调数列即可,然后搞了半天发现是错的,如图:
对于这种情况,当 $a[j]$ 还没超过 $a[i]$ 时,$a[k]$ 可能已经超过 $a[i]$ 了,所以我们不能把 $a[j]$ 放到数列里,不然就无法保证单调性
事实上,我们需要维护的是所有点对 $(x,a[x])$ 构成的上凸包,具体理由如下:
对于某个位置 $i$,如果 $a[i]$ 被超越,那么对于下一个位置 $k$ ,$i,k$ 之间必须不存在 $j$,使得
$a[i]+add*i-del>a[j]+add*j-del$ 并且 $a[k]+add*k-del>a[i]+add*i-del$
即 $(a[i]-a[j])/(i-j)<-add$ 且 $(a[i]-a[k])/(i-k)>-add$
即 $(a[i]-a[k])/(i-k)>(a[i]-a[j])/(i-j)$,发现左右两边其实就是连线的斜率,所以即维护一个上凸包
具体实现起来还是有一些细节的
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+,M=;
int n,m;
int bel[N],L[M],pos[M];
ll a[N],add[M],del[M];
vector <int> st[M];
inline void push_down(int o)
{
for(int i=L[o];i<L[o+];i++) a[i]+=add[o]*i-del[o];
add[o]=del[o]=pos[o]=; st[o].clear();
}
inline ll calc(int i,int o) { return a[i]+add[o]*i-del[o]; }
inline void upd(int o)
{
while(pos[o]<st[o].size()- && calc(st[o][pos[o]],o)<=calc(st[o][pos[o]+],o) ) pos[o]++;
}
inline void build(int o)
{
for(int i=L[o];i<L[o+];st[o].push_back(i),i++)
while(st[o].size()> &&
(a[i]-a[st[o][st[o].size()-]])*(st[o][st[o].size()-]-st[o][st[o].size()-]) >=
(a[st[o][st[o].size()-]]-a[st[o][st[o].size()-]])*(i-st[o][st[o].size()-]) ) st[o].pop_back();
upd(o);
}
inline void query(int l,int r)
{
int bl=bel[l-]+,br=bel[r+]-; ll res=;
if(bl>br)
{
for(int i=l;i<=r;i++) res=max(res, calc(i,bel[i]) );
printf("%lld\n",max(0ll,res-calc(,))); return;
}
for(int i=l;i<L[bl];i++) res=max(res, calc(i,bel[i]) );
for(int i=L[br+];i<=r;i++) res=max(res, calc(i,bel[i]) );
for(int i=bl;i<=br;i++) res=max(res, calc(st[i][pos[i]],i) );
printf("%lld\n",max(0ll,res-calc(,)));
}
inline void Swap(int x,int y)
{
push_down(bel[x]); push_down(bel[y]);
swap(a[x],a[y]);
build(bel[x]); build(bel[y]);
}
inline void change(int l,int r,int t)
{
int bl=bel[l-]+,br=bel[r+]-;
if(bl>br)
{
push_down(bel[l]); push_down(bel[r]);
for(int i=l;i<=r;i++) a[i]+=1ll*(i-l+)*t;
build(bel[l]); build(bel[r]); return;
}
if(L[bl]!=l)
{
for(int i=l;i<L[bl];i++) a[i]+=1ll*(i-l+)*t;
push_down(bl-); build(bl-);
}
if(L[br+]-!=r)
{
for(int i=L[br+];i<=r;i++) a[i]+=1ll*(i-l+)*t;
push_down(br+); build(br+);
}
for(int i=bl;i<=br;i++) add[i]+=t,del[i]+=1ll*(l-)*t,upd(i);
}
int main()
{
n=read(),m=read(); int T=sqrt(n)+;
for(int i=;i<=n;i++)
{
a[i]=read(); bel[i]=(i-)/T+;
if(bel[i]!=bel[i-]) L[bel[i]]=i;
}
bel[n+]=bel[n]+; L[bel[n+]]=n+;
for(int i=;i<=bel[n];i++) build(i);
int opt,a,b;
for(int i=;i<=m;i++)
{
opt=read(); a=read(),b=read();
if(opt==) { query(a,b); continue; }
if(opt==) { Swap(a,b); continue; }
change(a,b,read());
}
return ;
}
P2496 [SDOI2012]体育课的更多相关文章
- 【Luogu2496】【BZOJ3005】[SDOI2012]体育课
把自己去年在luogu写的一个题解搬过来 原题解链接 1. 题目大意 给定一个长度为 \(n\) 的数列 \(a_1,a_2,a_3,...,a_n\) , 并给出 \(m\) 个操作,操作类型如下: ...
- 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有关 ...
随机推荐
- CF1205C Palindromic Paths
题目链接 问题分析 首先可以想到,坐标和为奇数的位置可以被唯一确定.同样的,如果假定\((1,2)\)是\(0\),那么坐标和为偶数的位置也可以被唯一确定.这样总共使用了\(n^2-3\)次询问. 那 ...
- iview简单使用+按需加载组件的方法(全局和局部)
1,简单使用 vue项目中使用iview非常简单: 首先安装依赖: $ npm install iview --save 会安装最新版本的依赖,安装完成后package.json会出现如下图配置 表示 ...
- RESTful API Design
https://restful-api-design.readthedocs.org/en/latest/scope.html http://blog.mashape.com/30-ways-to-m ...
- go.js-拖拽流程图插件
1.去除水印 在文件中搜索7eba17a4ca3b1a8346,找到类似a.Jv=d[w.Jg("7eba17a4ca3b1a8346")][w.Jg("78a118b7 ...
- readyState xhr对象当前状态
var request=new XMLHttpRequest(); request.open("GET","get.php",true); request.se ...
- 在electron中使用sqlite:sql.js简介
在electron中使用sqlite:sql.js简介 在开发electron应用的时候如果想要使用sqlite3,步骤上除了npm安装以外还要rebuild,比较麻烦.如果你想找一个开箱即用的sql ...
- es6 字符串 对象 拓展 及 less 的语法
es6 字符串 对页面渲染的几种方式:字符串拼接 文档碎片 dom操作 模板 es6 又提供了一种新的对页面渲染的方式:字符串模板(高级版的字符串拼接) 模板字符串标识符是 反引号 ( `` ) 英文 ...
- leetcode 509斐波那契数列
递归方法: 时间O(2^n),空间O(logn) class Solution { public: int fib(int N) { ?N:fib(N-)+fib(N-); } }; 递归+记忆化搜索 ...
- flutter block回调
block回调在oc中很常见,到了flutter中仍然有block回调 自定义一个StatefulWidget PageTitle 无参数回调VoidCallback VoidCallback onT ...
- Linux_用户和权限管理
目录 目录 用户管理基础知识 用户管理指令 useradd userdel passwd usermod chage su id who chmod chown s权限t权限 acl 用户管理基础知识 ...