本题可以采用主席树的在线做法,只不过常数会 \(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. bugku Crypto 下半部分wp

    1. 百度托马斯这个人居然还发明了一种轮转的加密法,发现原理是,他将很多行乱序的26个字母,插到一根柱子上,参考糖葫芦的样子,可以旋转每一行,设置自己要发送的明文后,向对方发送乱码的一列,对方只要将这 ...

  2. C++11运算符重载详解与向量类重载实例(<<,>>,+,-,*等)

    1. C++运算符重载介绍 C ++ 中预定义的运算符的操作对象只能是基本数据类型.但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作.这时就必须在C ++ 中重新定义这些运算符,赋予已 ...

  3. spring、springmvc、springboot、springcloud的联系与区别

    spring和springMvc: 1. spring是一个一站式的轻量级的java开发框架,核心是控制反转(IOC)和面向切面(AOP),针对于开发的WEB层(springMvc).业务层(Ioc) ...

  4. java基础---常用类

    一.字符串类String String:字符串,使用一对""引起来表示,字符串常量池在方法区中 public final class String implements java. ...

  5. [网络流24题]最长k可重线段集[题解]

    最长 \(k\) 可重线段集 题目大意 给定平面 \(x-O-y\) 上 \(n\) 个开线段组成的集合 \(I\) ,和一个正整数 \(k\) .试设计一个算法,从开线段集合 \(I\) 中选取开线 ...

  6. 将make的输出(标准输出/标准错误输出)重定向到文件

    方式 描述符 含义 stdin 0 标准输入 stdout 1 标准输出 stderr 2 标准错误输出 1.想要把make输出的全部信息,输出到某个文件中 最常见的办法就是:make xxx > ...

  7. 家庭账本开发day03

    今天在编写form表单提交时遇到很多问题,在向servlet提交请求时找不到资源, 在网上查找学习了相关的信息,找到原因,添加注解或者配置xml文件的相关映射 解决问题.成功完成了账单添加的功能.

  8. 【剑指offer】28. 对称的二叉树

    剑指 Offer 28. 对称的二叉树 知识点:二叉树:递归 题目描述 请实现一个函数,用来判断一棵二叉树是不是对称的.如果一棵二叉树和它的镜像一样,那么它是对称的. 示例 输入:root = [1, ...

  9. CF1214E Petya and Construction Set题解

    原来这就叫构造题,了 这道题的做法,我自己诌了一个形象的名字--"挂葡萄"法( 首先,"搭葡萄架":考虑到每个距离 \(d_i\) 只与 \(2i-1,2i\) ...

  10. python中的abstractmethod

    # -*- coding: utf-8 -*- from abc import ABC ,abstractclassmethod from collections import namedtuple ...