[BZOJ4826] [HNOI2017] 影魔 单调栈 主席树
因为是一个排列,所以不会有重复的。如果有重复就没法做了。一开始没有仔细看题目想了半天。
发现,如果是第一种情况,那么边界\(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] 影魔 单调栈 主席树的更多相关文章
- BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树
https://www.lydsy.com/JudgeOnline/problem.php?id=4826 年少不知空间贵,相顾mle空流泪. 和上一道主席树求的东西差不多,求两种对 1. max(a ...
- 【bzoj4826】[Hnoi2017]影魔 单调栈+可持久化线段树
题目描述 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...
- 【BZOJ4826】[Hnoi2017]影魔 单调栈+扫描线
[BZOJ4826][Hnoi2017]影魔 Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝 ...
- BZOJ 4826: [Hnoi2017]影魔 单调栈+可持久化线段树
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样 的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个 ...
- [BZOJ4826][HNOI2017]影魔 可持久化线段树
链接 题意:给你 \(1\) 到 \(n\) 的排列 \(k_1,k_2,\dots,k_n\) ,对 \(i,j (i<j)\)来说,若不存在 \(k_s (i<s<j)\) 大于 ...
- 洛谷P4198 楼房重建 单调栈+线段树
正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...
- 2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)
2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...
- [bzoj4826][Hnoi2017]影魔_单调栈_主席树
影魔 bzoj-4826 Hnoi-2017 题目大意:给定一个$n$个数的序列$a$,求满足一下情况的点对个数: 注释:$1\le n,m\le 2\cdot 10^5$,$1\le p1,p2\l ...
- 【ZJOI2017 Round2练习&BZOJ4826】D1T2 sf(主席树,单调栈)
题意: 思路:From http://blog.csdn.net/neither_nor/article/details/70211150 对每个点i,单调栈求出左边和右边第一个大于i的位置,记为l[ ...
随机推荐
- properties与yml之间的比较
在Spring Cloud的配置文件中,发现使用yml与properties两种后缀的文件: 在application.properties中内容是这样的: server.port=8801eurek ...
- wl
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Conten ...
- video.js播放rtmp
项目中要用到rtmp直播和点播.要求:点播能够调整播放进度 开始用腾讯提供的播放器,老卡,画质差,很多时候播不出来,rtmp点播还不能快进. 后来用Wowza自带的flash rtmp播放器,有源码 ...
- Linux下安装mysql教程
Linux下安装mysql MySQL官网:https://dev.mysql.com/downloads/mysql/ 到mysql官网下载mysql编译好的二进制安装包,在下载页面Select ...
- C#连redis
引入 Microsoft.Extensions.Caching.Redis其实就是封装了StackExchange.redis 控制台例子: class Program { public static ...
- python之环境变量(测试环境可配置)
想要实现的结果是: 执行脚本时,带一个参数,由这个参数来决定测试环境(开发or测试),比如: python test.py dev 实现代码: 方式1 不用__getitem__方式: import ...
- delphi 牛逼 了 app (已在软件界掀起波澜)10分钟10行代码做出让人惊叹的程序
(已在软件界掀起波澜)10分钟10行代码做出让人惊叹的程序 http://v.qq.com/x/page/m0328h73bs7.html?ptag=bbs_csdn_net
- RSA - 原理、特点(加解密及签名验签)及公钥和私钥的生成
Wiki - RSA加密演算法 Wiki - 欧拉函数 Wiki - 模反元素 ASN.1 格式标准 RSA算法原理(二) 注意: RSA 加密或签名后的结果是不可读的二进制,使用时经常会转为 BAS ...
- Easyui表格显示日期格式错误
问题 如下图: 解决办法: 以Sql Server 2008为例,在执行查询时,把“采购日期”字段由datetime转换为string,前端以string类型显示.
- Show Me the Code
最近在练习写Python代码,拥有150多道程序员面试题的LeetCode注重算法的实现,锻炼思维,还能在线测试代码的正确性,而Python练习册涉及到了Python实际的应用,锻炼解决问题的能力,托 ...