传送门

分块

对每个块维护一个 $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]体育课的更多相关文章

  1. 【Luogu2496】【BZOJ3005】[SDOI2012]体育课

    把自己去年在luogu写的一个题解搬过来 原题解链接 1. 题目大意 给定一个长度为 \(n\) 的数列 \(a_1,a_2,a_3,...,a_n\) , 并给出 \(m\) 个操作,操作类型如下: ...

  2. BZOJ 2705: [SDOI2012]Longge的问题 [欧拉函数]

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 2553  Solved: 1565[Submit][ ...

  3. BZOJ 2705: [SDOI2012]Longge的问题

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 2554  Solved: 1566[Submit][ ...

  4. 【BZOJ】【2705】【SDOI2012】Longge的问题

    欧拉函数/狄利克雷卷积/积性函数 2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1275  Solv ...

  5. BZOJ 2705: [SDOI2012]Longge的问题 GCD

    2705: [SDOI2012]Longge的问题 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnl ...

  6. bzoj 2706: [SDOI2012]棋盘覆盖 Dancing Link

    2706: [SDOI2012]棋盘覆盖 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 255  Solved: 77[Submit][Status] ...

  7. bzoj 2705: [SDOI2012]Longge的问题 歐拉函數

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1035  Solved: 669[Submit][S ...

  8. Bzoj 2705: [SDOI2012]Longge的问题 欧拉函数,数论

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1959  Solved: 1229[Submit][ ...

  9. BZOJ 2726: [SDOI2012]任务安排( dp + cdq分治 )

    考虑每批任务对后面任务都有贡献, dp(i) = min( dp(j) + F(i) * (T(i) - T(j) + S) ) (i < j <= N)  F, T均为后缀和. 与j有关 ...

随机推荐

  1. bootstrap editable有默认值

    function listEditor(data,productCode) { $('#tab1').bootstrapTable('load', data); $('#tab1').bootstra ...

  2. 20175215 2018-2019-2 第二周java课程学习总结

    一.学生免费申请使用IDEA 下载好IDEA后,设置到最后有一个界面, 我们需要到IDEA官网进行IDEA免费试用权的申请,如果有学校的邮箱,使用学校的邮箱注册并证明是自己的就可以直接通过申请.如下图 ...

  3. 在RHEL6_Oracle_Linux_6上生成正确的udev_rule_规则文件

    1. #首先确认是 Linux 6.0以上版本 [root@vrh6 dev]# cat /etc/issue          Oracle Linux Server release 6.2Kern ...

  4. golang tcp keepalive实践

    前文中已经介绍了TCP keep alive的做了详尽说明,本文结合golang,介绍如何使用TCP keep alive. 目前golang net包不提供TCP keep alive 空闲多长时间 ...

  5. Electron对JQuery的支持问题

    最近在了解Electron框架写应用,偶然发现在html中使用<script src="./jquery.js"></script>这种方式引入JQuery ...

  6. 获取手机本地IP地址

    public String getLocalIpAddress() { try { for (Enumeration<NetworkInterface> en = NetworkInter ...

  7. Python的组合模式与责任链模式编程示例

    Python的组合模式与责任链模式编程示例 这篇文章主要介绍了Python的组合模式与责任链模式编程示例,组合模式与责任链模式都属于Python的设计模式,需要的朋友可以参考下 组合模式 我们把Com ...

  8. Delphi中的Free和Nil和freeandnil函数

    Delphi中的Free和Nil 在Delphi中释放对象资源时一般用Obj.Free(Obj为一个实例名),不过程Delphi中还有一个FreeAndNil(对象名)函数,那么用哪个好呢?Free和 ...

  9. The window object

    At the core of the BOM is the window object, which represents an instance of the browser. The window ...

  10. spring ehcache 缓存框架

    一.简介 Ehcache是一个用Java实现的使用简单,高速,实现线程安全的缓存管理类库,ehcache提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的cache管理方案.同时ehcache ...