本题可以采用主席树的在线做法,只不过常数会 \(super\) 大。

和其他题解差不多,我们先要求出第 \(i\) 个数的 \(l_i\) 和 \(r_i\) ,其中 \(l_i\) 表示左边第一个比它大的点(若没有则为 \(0\) ), \(r_i\) 表示右边比它大的第一个点,若没有则为 \(n+1\) 。

那么对于 \(i\)

  1. 点对 \((l_i,r_i)\) 可以有 \(p_1\) 的贡献

  2. 点对 \(([l_i+1,i-1],r_i),(l_i,[i+1,r_i-1])\) 可以有 \(p_2\) 的贡献 \((l_i+1<i-1),(i+1<r_i-1)\)

  3. \((i,i+1)\) 也可以有 \(p_1\) 的贡献

有了这么几点,我们就可以拿主席树来维护,对于每个点对,我们以 \(x\) 更新,若 \(x\) 为区间,则以 \(y\) 更新。

用一个单调栈预处理,链表(或 \(vector\) 存储更新信息)。

\(AC \kern 0.4emCODE\):

#include<bits/stdc++.h>
#define ri register int
#define p(i) ++i
#define LL long long
using namespace std;
const int N=2e5+7;
inline int read() {
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
struct node{
int l,r,w;
node(){}
node(int l,int r,int w):l(l),r(r),w(w){}
};
struct E{
int first[N],t;
void init() {t=1;}
struct edge{
int nxt;
node v;
}e[N<<2];
inline void add(int u,node v) {
e[t].v=v;
e[t].nxt=first[u];
first[u]=t++;
}
}E;
struct Seg{
int root[N],tot;
struct Segmenttree{
int l,r;
LL sum,tag;
}T[N*32];
inline void update(int &x,int l,int r,int lt,int rt,int w) {
if (!x) x=p(tot);
T[x].sum+=1ll*(min(r,rt)-max(l,lt)+1)*w;
if (l<=lt&&rt<=r) {T[x].tag+=1ll*w;return;}
int mid=(lt+rt)>>1;
if (l<=mid) update(T[x].l,l,r,lt,mid,w);
if (r>mid) update(T[x].r,l,r,mid+1,rt,w);
}
inline int merge(int x,int y) {
if (!x||!y) return x+y;
T[x].sum+=T[y].sum;T[x].tag+=T[y].tag;
T[x].l=merge(T[x].l,T[y].l);
T[x].r=merge(T[x].r,T[y].r);
return x;
}
inline LL query(int x,int l,int r,int lt,int rt) {
if (!x) return 0;
if (l<=lt&&rt<=r) return T[x].sum;
int mid=(lt+rt)>>1;LL res=0;
if (l<=mid) res+=query(T[x].l,l,r,lt,mid);
if (r>mid) res+=query(T[x].r,l,r,mid+1,rt);
return res+1ll*(min(r,rt)-max(l,lt)+1)*T[x].tag;
}
}T;
int n,st[N],p,pp,at[N],ll[N],rr[N],m;
int main() {
n=read(),m=read(),p=read(),pp=read();
const int p1=p,p2=pp;
int tp=0;
for (ri i(1);i<=n;p(i)) {
at[i]=read();
while(tp&&at[st[tp]]<at[i]) rr[st[tp--]]=i;
ll[i]=st[tp];
st[p(tp)]=i;
}
while(tp) rr[st[tp--]]=n+1;
E.init();
for (ri i(1);i<=n;p(i)) {
if (i!=n) E.add(i,node(i+1,i+1,p1));
if (ll[i]&&rr[i]<=n) E.add(ll[i],node(rr[i],rr[i],p1));
if (ll[i]&&i+1<=rr[i]-1) E.add(ll[i],node(i+1,rr[i]-1,p2));
if (rr[i]<=n&&ll[i]+1<=i-1) E.add(rr[i],node(ll[i]+1,i-1,p2));
}
for (ri i(1);i<=n;p(i)) {
for (ri j(E.first[i]);j;j=E.e[j].nxt) {
node v=E.e[j].v;
int l=v.l,r=v.r,w=v.w;
T.update(T.root[i],l,r,1,n,w);
}
T.root[i]=T.merge(T.root[i],T.root[i-1]);
}
for (ri i(1);i<=m;p(i)) {
int l=read(),r=read();
printf("%lld\n",T.query(T.root[r],l,r,1,n)-T.query(T.root[l-1],l,r,1,n));
}
return 0;
}

BZOJ 4826 影魔的更多相关文章

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

    4826: [Hnoi2017]影魔 题意:一个排列,点对\((i,j)\),\(p=max(i+1,j-1)\),若\(p<a_i,a_j\)贡献p1,若\(p\)在\(a_1,a_2\)之间 ...

  2. BZOJ:4826: [Hnoi2017]影魔

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

  3. ●BZOJ 4826 [Hnoi2017]影魔

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4826 题解: 主席树,单调栈 以前还没做过这种维护信息的题,感觉好奇妙. 每对相邻的两个数所 ...

  4. BZOJ.4826.[AHOI/HNOI2017]影魔(树状数组/莫队 单调栈)

    BZOJ LOJ 洛谷 之前看\(mjt\)用莫队写了,以为是一种正解,码了3h结果在LOJ T了没A= = 心态爆炸(upd:发现是用C++11(NOI)交的,用C++11交就快一倍了...) 深刻 ...

  5. BZOJ 4826 【HNOI2017】 影魔

    题目链接:影魔 这道题就是去年序列的弱化版啊…… 我们枚举最大值的位置\(i\),找出左边第一个比\(a_i\)大的位置\(l\),右边第一个比\(a_i\)大的位置\(r\),然后我们分开考虑一下\ ...

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

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

  7. AC日记——[Hnoi2017]影魔 bzoj 4826

    4826 思路: 主席树矩阵加减+单调栈预处理: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 200005 ...

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

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

  9. BZOJ 4826 [Hnoi2017]影魔 ——扫描线 单调栈

    首先用单调栈和扫描线处理出每一个数左面最近的比他大的数在$l[i]$,右面最近的比他大的数$r[i]$. 然后就可以考虑每种贡献是在什么时候产生的. 1.$(l[i],r[i])$产生$p1$的贡献 ...

随机推荐

  1. 《PHP设计模式大全》系列分享专栏

    <PHP设计模式大全>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/read/201739.html 文章 php设计模式介绍之编程惯用法第 ...

  2. 【源码篇】Flutter GetX深度剖析 | 我们终将走出自己的路(万字图文)

    前言 人心中的成见是一座大山,任你怎么努力都休想搬动. 这是电影<哪吒>里申公豹说的一句话,也是贯彻整部电影的一个主题:或许这句话引起了太多人的共鸣:35岁职场危机,大厂卡本科学历,无房无 ...

  3. 必须要了解的Linux基本操作

    Linux常用的基础操作             1.命令行提示字符             2.切换用户             3.查看当前主机的完整名称             4.临时设置主机 ...

  4. C语言:数组数据交换

    //交换数组中各个变量的值:第1和最后一个交换,第2与倒数第二个交换 #include <stdio.h> int main() { int a[]={1,2,3,4,5,6,7,8,9} ...

  5. scrapy::Max retries exceeded with url

    运行scrapy时出错这个错误:Max retries exceeded with url解决方法: img1=requests.get(url=aa,headers=header1,timeout= ...

  6. C语言:文件

    文件是数据源的一种,最主要的作用是保存数据.在操作系统中,为了统一对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件.对这些文件的操作,等同于对磁盘上普通文件的操作.例如: 通常把显示器称为 ...

  7. python 分析文本文件

    def count_words(filename):#统计指定文件单词的数量 """Count the approximate number of words in a ...

  8. C++之vector容器

    一.STL的基本概念 STL(Standard Template Library)标准模板库大体上分为六大组件,分别为容器,算法,迭代器,仿函数,适配器和空间配置器,其中最重要的是容器,算法和迭代器, ...

  9. POJ1704 Georgia and Bob 题解

    阶梯博弈的变形.不知道的话还是一道挺神的题. 将所有的棋子两两绑在一起,对于奇数个棋子的情况,将其与起点看作一组.于是便可以将一组棋子的中间格子数看作一推石子.对靠右棋子的操作是取石子,而对左棋子的操 ...

  10. [考试总结]noip模拟6

    我好菜啊 真上次第二这次倒二... 因为昨天还没有改完所有的题所以就留到今天来写博客了 这次考试总结的教训有很多吧,反正处处体现XIN某人的laji,自己考试的是后本以为一共四个题目,三个题目都没有看 ...