题面

因为是一个排列,所以不会有重复的。如果有重复就没法做了。一开始没有仔细看题目想了半天。

发现,如果是第一种情况,那么边界\(l\)和\(r\)就应该分别是整个区间的最大值和次大值。

然后,对于那第二种情况, \(l\)和\(r\)中,只有一个数是最大值,另一个数不可以是最大值和次大值。

于是我们考虑从每一个合法区间内数里面选出一个代表来可以直接代表整个区间。

用单调栈维护一下\(lp[i]\)和\(rp[i]\)分别表示一个数左边和右边离\(i\)最近的大于之的数。

然后对于第一种情况,发现相邻两个数一定是对的。然后发现,任何一个\([lp[i],rp[i]]\)也是对的。因为可以保证边界上的数的最大与次大的性质。

那么第二种呢?只要保证一个边界最大即可,因此就是\([lp[i]+1..i-1,rp[i]]\)和\([lp[i],i+1..rp[i]-1]\)。可以保证不会重复,因为这里\(i\)实际上是每个区间的次大值,每个区间只会被其次大值统计一次。

于是我们考虑把一个区间的边界位置分别作为二维的坐标,发现问题就变成了求以\(l,l\)和\(r,r\)为顶点的正方形内的和。

显然可以用扫描线。但是其实可以更方便。每一个位置只能是一个线段,所以我们直接用主席树维护一下即可。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#define REP(i,a,n) for(register int i(a);i<=(n);++i)
#define PER(i,a,n) for(register int i(a);i>=(n);--i)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
const int SZ=(1<<21)+1;char ibuf[SZ],*iS,*iT,obuf[SZ+128],*oS=obuf,*oT=obuf+SZ-1;
#ifndef ONLINE_JUDGE
#define gc() getchar()
#else
#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SZ,stdin),iS==iT?EOF:*iS++):*iS++)
#endif
template<typename I>inline void read(I&x){char c=gc();int f=1;for(;c<'0'||c>'9';c=gc())c=='-'?f=-1:0;for(x=0;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+(c&15);f==-1?x=-x:0;}
inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
#define printf(...) oS>oT&&(flush(),1),oS+=sprintf(oS,__VA_ARGS__)
typedef long long ll;typedef unsigned long long ull;
template<typename A,typename B>inline char SMAX(A&a,const B&b){return a<b?a=b,1:0;}
template<typename A,typename B>inline char SMIN(A&a,const B&b){return a>b?a=b,1:0;} const int N=200000+7;
int n,m,T,p1,p2,a[N],x,y,q[N],tl,lp[N],rp[N]; struct Node{int lc,rc,lps;ll val,add;}t[N*50];int RT[N],nod;//错误笔记:这里不是单调修改,所以仅仅开LOG被是不够的
inline void Insert(int &o,int L,int R,int l,int r,int k){
if(t[o].lps<T)t[++nod]=t[o],o=nod,t[o].lps=T;
if(l<=L&&R<=r)return (void)(t[o].add+=k,t[o].val+=(ll)k*(R-L+1));
int M=(L+R)>>1;if(l<=M)Insert(t[o].lc,L,M,l,r,k);if(r>M)Insert(t[o].rc,M+1,R,l,r,k);
t[o].val=t[t[o].lc].val+t[t[o].rc].val+t[o].add*(R-L+1);
}
inline ll Query(int o,int p,int L,int R,int l,int r,ll adv){
if(l<=L&&R<=r)return t[o].val-t[p].val+adv*(R-L+1);
int M=(L+R)>>1;if(r<=M)return Query(t[o].lc,t[p].lc,L,M,l,r,adv+t[o].add-t[p].add);else if(l>M)return Query(t[o].rc,t[p].rc,M+1,R,l,r,adv+t[o].add-t[p].add);
else return Query(t[o].lc,t[p].lc,L,M,l,r,adv+t[o].add-t[p].add)+Query(t[o].rc,t[p].rc,M+1,R,l,r,adv+t[o].add-t[p].add);
} struct Pair{int x,y,w;};std::vector<Pair>g[N];
inline void Preprocess(){
REP(i,1,n){
while(tl&&a[q[tl]]<a[i])--tl;
q[++tl]=i;lp[i]=q[tl-1];
}q[tl=0]=n+1;PER(i,n,1){
while(tl&&a[q[tl]]<a[i])--tl;
q[++tl]=i;rp[i]=q[tl-1];
if(i<n)g[i].push_back(Pair{i+1,i+1,p1});
if(lp[i]&&rp[i]<=n)g[rp[i]].push_back(Pair{lp[i],lp[i],p1});
if(rp[i]<=n&&i-1>=lp[i]+1)g[rp[i]].push_back(Pair{lp[i]+1,i-1,p2});
if(lp[i]&&i+1<=rp[i]-1)g[lp[i]].push_back(Pair{i+1,rp[i]-1,p2});
}
REP(i,1,n){
T=i;RT[i]=RT[i-1];int len=g[i].size();
REP(j,0,len-1)Insert(RT[i],1,n,g[i][j].x,g[i][j].y,g[i][j].w);
}
} int main(){
read(n);read(m),read(p1),read(p2);
REP(i,1,n)read(a[i]);
Preprocess();
REP(i,1,m){
read(x),read(y);
printf("%lld\n",Query(RT[y],RT[x-1],1,n,x,y,0));
}return flush(),0;
}

[BZOJ4826] [HNOI2017] 影魔 单调栈 主席树的更多相关文章

  1. BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树

    https://www.lydsy.com/JudgeOnline/problem.php?id=4826 年少不知空间贵,相顾mle空流泪. 和上一道主席树求的东西差不多,求两种对 1. max(a ...

  2. 【bzoj4826】[Hnoi2017]影魔 单调栈+可持久化线段树

    题目描述 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...

  3. 【BZOJ4826】[Hnoi2017]影魔 单调栈+扫描线

    [BZOJ4826][Hnoi2017]影魔 Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝 ...

  4. BZOJ 4826: [Hnoi2017]影魔 单调栈+可持久化线段树

    Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样 的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个 ...

  5. [BZOJ4826][HNOI2017]影魔 可持久化线段树

    链接 题意:给你 \(1\) 到 \(n\) 的排列 \(k_1,k_2,\dots,k_n\) ,对 \(i,j (i<j)\)来说,若不存在 \(k_s (i<s<j)\) 大于 ...

  6. 洛谷P4198 楼房重建 单调栈+线段树

    正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...

  7. 2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)

    2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...

  8. [bzoj4826][Hnoi2017]影魔_单调栈_主席树

    影魔 bzoj-4826 Hnoi-2017 题目大意:给定一个$n$个数的序列$a$,求满足一下情况的点对个数: 注释:$1\le n,m\le 2\cdot 10^5$,$1\le p1,p2\l ...

  9. 【ZJOI2017 Round2练习&BZOJ4826】D1T2 sf(主席树,单调栈)

    题意: 思路:From http://blog.csdn.net/neither_nor/article/details/70211150 对每个点i,单调栈求出左边和右边第一个大于i的位置,记为l[ ...

随机推荐

  1. springboot整合hibernate案例

    1.运行环境 开发工具:intellij idea JDK版本:1.8 项目管理工具:Maven 4.0.0 2.GITHUB地址 https://github.com/nbfujx/springBo ...

  2. [java] [error] java.lang.OutOfMemoryError: unable to create new native thread

    前言 最近公司的服务器出现了oom的报错,经过一番排查,终于找到了原因.写下这篇博客是为了记录下查找的过程,也是为了帮助那些跟我门遇到的情况相同的人可以更快的寻找到答案. 环境 系统:linux(ce ...

  3. 笨办法学Python(learn python the hard way)--练习程序39-40

    下面是练习39-练习40,基于python3 #ex39.py 1 ten_things = "Apples Oranges Crows Telephone Light Sugar" ...

  4. IDEA设置Ctrl+滚轮调整字体大小(转载)

    按Ctrl+Shift+A,出现搜索框 输入mouse: 点击打开这个设置:勾选 点击ok,之后就可以通过Ctrl+滚轮 调整字体大小了. 转载自:http://www.cnblogs.com/LUA ...

  5. POI样式

    5.POI样式 在Excel应用中,会需要用到各种样式,包括单元格背景色.边框.高度.宽度.内容相对位置.字体格式.字体大小.字体颜色等等.POI提供了一系列的样式,能满足我们一般开发中的需求. 5. ...

  6. 51nod 1205 流水线调度

    1205 流水线调度 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 N个作业{1,2,…,n}要在由2台机器M1和M2组成的流水线上完成加工.每个 ...

  7. keras:InternalError: Failed to create session

    如题,keras出现以上错误,解决办法: 找到占用gpu的进程: nvidia-smi -q 杀死这些进程即可: xxxxx

  8. Webhook到底是个啥?

    参照: https://segmentfault.com/a/1190000015437514

  9. js中return;、return true、return false的区别

    一.返回控制与函数结果, 语法为:return 表达式; 语句结束函数执行,返回调用函数,而且把表达式的值作为函数的结果  二.返回控制, 无函数结果,语法为:return;  在大多数情况下,为事件 ...

  10. MySQL 服务器性能剖析

    这是<高性能 MySQL(第三版)>第三章的读书笔记. 关于服务,常见的问题有: 如何确认服务器是否发挥了最大性能 找出执行慢的语句,为何执行慢 为何在用户端发生间歇性的停顿.卡死 通过性 ...