[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[ ...
随机推荐
- linux如何查看端口被哪个进程占用的方法
linux如何查看端口被哪个进程占用的方法: 1.lsof -i:端口号2.netstat -tunlp|grep 端口号 都可以查看指定端口被哪个进程占用的情况[步骤一]lsof -ilsof -i ...
- Oracle dmp文件(表)导入与导出
dmp文件是作为oracle导入和导出表使用的文件格式dmp文件导出dmp文件导出用的比较多的一般是三种,他们分别是:1.导出整个数据库实例下的所有数据2.导出指定用户的所有表3.导出指定表. 打开命 ...
- 修改MySQL表varchar字段的小实验
将actor表的first_name的varchar(45) ,修改为varchar(60) [root@vhost1 ~]# mysql -uroot -p -S /mysqldata/tmp/my ...
- 129、TensorFlow计算图的可视化
import tensorflow as tf # Build your graph x = tf.constant([[37.0, -23.0], [1.0, 4.0]], name="i ...
- npm install 安装不成功,提示python2.7
npm install 安装不成功的原因 是因为缺少python的环境 解决方法: 1.去官网下载https://www.python.org/download/releases/2.7/ 2.安装成 ...
- WCF身份验证之用户名密码认证
WCF支持多种认证技术,例如Windowns认证.X509证书.Issued Tokens.用户名密码认证等,在跨Windows域分布的系统中,用户名密码认证是比较常用的,要实现用户名密码认证,就必须 ...
- Oracle客户端和服务端的区别
转载:https://blog.csdn.net/qq_22558507/article/details/75220224 随着Oracle技术领域应用越来越广泛,现在就关于oracle客户端配置极其 ...
- IOS-问题整理
安装包相关 安装包无法打开 通用中点击验证应用无反应 卸载-删除证书-重装
- CF1105C Ayoub and Lost Array ——动态规划
CF1105C Ayoub and Lost Array 题意:一个整数数组,满足: 1. 长度为n 2. 所有元素都在[l, r]范围内 3. 所有元素的和能被3整除给出n, l, r (1 ≤ n ...
- dp(最长公共上升子序列)
This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence ...