Description

影魔,奈文摩尔,据说有着一个诗人的灵魂。事实上,他吞噬的诗人灵魂早已成千上万。千百年来,他收集了各式各样的灵魂,包括诗人、牧师、帝王、乞丐、奴隶、罪人,当然,还有英雄。每一个灵魂,都有着自己的战斗力,而影魔,靠这些战斗力提升自己的攻击。奈文摩尔有 n 个灵魂,他们在影魔宽广的体内可以排成一排,从左至右标号 1 到 n。第 i个灵魂的战斗力为 k[i],灵魂们以点对的形式为影魔提供攻击力,对于灵魂对 i,j(i<j)来说,若不存在 k[s](i<s<j)大于 k[i]或者 k[j],则会为影魔提供 p1 的攻击力(可理解为:当 j=i+1 时,因为不存在满足 i<s<j 的 s,从而 k[s]不存在,这时提供 p1 的攻击力;当 j>i+1 时,若max{k[s]|i<s<j}<=min{k[i],k[j]},则提供p1的攻击力 ); 另一种情况,令c为k[i+1],k[i+2],k[i+3]......k[j-1]的最大值,若 c 满足:k[i]<c<k[j],或者 k[j]<c<k[i],则会为影魔提供 p2 的攻击力,当这样的 c 不存在时,自然不会提供这 p2 的攻击力;其他情况的点对,均不会为影魔提供攻击力。影魔的挚友噬魂鬼在一天造访影魔体内时被这些灵魂吸引住了,他想知道,对于任意一段区间[a,b],1<=a<b<=n,位于这些区间中的灵魂对会为影魔提供多少攻击力,即考虑 所有满足a<=i<j<=b的灵魂对i,j提供的攻击力之和。顺带一提,灵魂的斗力组成一个 1 到 n 的排列:k[1],k[2],...,k[n]。

Input

第一行 n,m,p1,p2
第二行 n 个数:k[1],k[2],...,k[n]
接下来 m 行,每行两个数 a,b,表示询问区间[a,b]中的灵魂对会为影魔提供多少攻击力。
1 <= n,m <= 200000;1 <= p1,p2 <= 1000

Output

共输出 m 行,每行一个答案,依次对应 m 个询问。

Sample Input

10 5 2 3
7 9 5 1 3 10 6 8 2 4
1 7
1 9
1 3
5 9
1 5

Sample Output

30
39
4
13
16
 
这种题目想+码花了快2小时我是不是药丸啊……
离线,从左到右扫,维护一下最大值的栈,用线段树做修改没了。
1A还是比较开心的。
#include<cstdio>
#include<algorithm>
#define MN 210000
#define lp (p<<1)
#define rp ((p<<1)|1)
#define ll long long
using namespace std; int read_p,read_ca;
inline int read(){
read_p=;read_ca=getchar();
while(read_ca<''||read_ca>'') read_ca=getchar();
while(read_ca>=''&&read_ca<='') read_p=read_p*+read_ca-,read_ca=getchar();
return read_p;
}
struct tree{int si,s,t[];ll sum;tree(){s=t[]=t[]=sum=;}}t[MN<<];
struct ask{int l,r,p;}qu[MN];
bool operator < (ask a,ask b){return a.r<b.r;}
int n,m,p1,p2,a[MN],q=,st[MN],num=,top;ll MMH[MN];
inline void hb(int p,int ty,int v){
if (ty){
if (t[p].s==) return;
t[p].t[]+=v;t[p].sum+=1LL*v*t[p].s;
}else{
if (t[p].s==t[p].si) return;
t[p].t[]+=v;t[p].sum+=1LL*v*(t[p].si-t[p].s);
}
}
inline void pd(int p){
if (t[p].t[]){
hb(lp,,t[p].t[]);
hb(rp,,t[p].t[]);
t[p].t[]=;
}
if (t[p].t[]){
hb(lp,,t[p].t[]);
hb(rp,,t[p].t[]);
t[p].t[]=;
}
}
void ADD(int p,int l,int r,int pos){
t[p].s++;
if (l==r) return;
pd(p);
int mid=l+r>>;
if (pos<=mid) ADD(lp,l,mid,pos);else ADD(rp,mid+,r,pos);
}
void del(int p,int l,int r,int pos){
t[p].s--;
if (l==r) return;
pd(p);
int mid=l+r>>;
if (pos<=mid) del(lp,l,mid,pos);else del(rp,mid+,r,pos);
}
void add(int p,int l,int r,int L,int R,int ty,int v){
if (ty){
if (t[p].s==) return;
}else if (t[p].s==t[p].si) return;
if (l==L&&r==R){hb(p,ty,v);return;}
pd(p);
int mid=l+r>>;
if (R<=mid) add(lp,l,mid,L,R,ty,v);else
if (L>mid) add(rp,mid+,r,L,R,ty,v);else
add(lp,l,mid,L,mid,ty,v),add(rp,mid+,r,mid+,R,ty,v);
t[p].sum=t[lp].sum+t[rp].sum;
}
ll ask(int p,int l,int r,int L,int R){
if (l==L&&r==R) return t[p].sum;
int mid=l+r>>;
pd(p);
if (R<=mid) return ask(lp,l,mid,L,R);else
if (L>mid) return ask(rp,mid+,r,L,R);else
return ask(lp,l,mid,L,mid)+ask(rp,mid+,r,mid+,R);
}
void build(int p,int l,int r){
t[p].si=r-l+;
if (l==r) return;
int mid=l+r>>;
build(lp,l,mid);build(rp,mid+,r);
}
int main(){
register int i,j;
n=read();m=read();p1=read();p2=read();
for (i=;i<=n;i++) a[i]=read();a[]=n+;
for (i=;i<=m;i++) qu[i].l=read(),qu[i].r=read(),qu[i].p=i;
sort(qu+,qu++m);st[top=]=;
build(,,n);
for (i=;i<=m;i++){
for (;q<=qu[i].r;q++){
for (j=top;a[st[j]]<a[q];j--);
if (q!=) add(,,n,st[j]+(j==),q-,,p1);
if (st[j]>) add(,,n,,st[j]-,,p2);
if (j!=top) add(,,n,st[j]+,q-,,p2);
while (a[st[top]]<a[q]) del(,,n,st[top--]);
ADD(,,n,st[++top]=q);
}
MMH[qu[i].p]=ask(,,n,qu[i].l,qu[i].r);
}
for (i=;i<=m;i++) printf("%lld\n",MMH[i]);
}

BZOJ:4826: [Hnoi2017]影魔的更多相关文章

  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]影魔

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

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

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

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

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

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

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

  6. bzoj 4826: [Hnoi2017]影魔【单调栈+树状数组+扫描线】

    参考:https://www.cnblogs.com/lcf-2000/p/6789680.html 这是一个相对码量少的做法,用到了区间修改区间查询的树状数组,详见:www.cnblogs.com/ ...

  7. 4826: [Hnoi2017]影魔

    4826: [Hnoi2017]影魔 https://lydsy.com/JudgeOnline/problem.php?id=4826 分析: 莫队+单调栈+st表. 考虑如何O(1)加入一个点,删 ...

  8. [BZOJ4826][HNOI2017]影魔(主席树)

    4826: [Hnoi2017]影魔 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 669  Solved: 384[Submit][Status][ ...

  9. 【LG3722】[HNOI2017]影魔

    [LG3722][HNOI2017]影魔 题面 洛谷 题解 先使用单调栈求出\(i\)左边第一个比\(i\)大的位置\(lp_i\),和右边第一个比\(i\)大的位置\(rp_i\). 考虑\(i\) ...

随机推荐

  1. 解析JSON的两种方法eval()和JSON.parse()

    解析JSON 一种方法是使用eval函数. var dataObj = eval("("+json+")"); 必须把文本包围在括号中,这样才能避免语法错误,迫 ...

  2. Java IO详解(四)------字符输入输出流

    File 类的介绍:http://www.cnblogs.com/ysocean/p/6851878.html Java IO 流的分类介绍:http://www.cnblogs.com/ysocea ...

  3. JAVA 用数组实现 ArrayList

    我们知道 ArrayList 是一个集合,它能存放各种不同类型的数据,而且其容量是自动增长的.那么它是怎么实现的呢? 其实 ArrayList 的底层是用 数组实现的.我们查看 JDK 源码也可以发现 ...

  4. 妙味课堂:JavaScript初级--第12课:json与数组

    1.json数据格式及json语法 <!DOCTYPE html> <html lang="en"> <head> <meta chars ...

  5. 命令行执行Django脚本的方法

    update.py import os import sys import django sys.path.append(r'C:\Users\Administrator\PycharmProject ...

  6. thinkinginjava学习笔记06_复用类

    MarsEdit粘代码好麻烦,所有代码交给github:https://github.com/lozybean/MyJavaLearning 复用一个类常用的两种方式:组合.继承: 组合 将对象引用置 ...

  7. thinkinginjava学习笔记04_初始化与清理

    java沿用了c++的构造器,使用一个和类名完全一样的方法作为类的构造器,可以有多个构造器来通过不同的参数进行构造,称为重载:不仅是构造器可以重载,其他方法也一样通过不同的形参以及不同的返回值来实现重 ...

  8. vue2.0 如何在hash模式下实现微信分享

    最近又把vue的demo拿出来整理下,正好要做"微信分享"功能,于是遇到新的问题: 由于hash模式下,带有"#",导致微信分享的签证无效:当改成history ...

  9. html5 storage事件

    HTML5 虽然很多年了,但是真的了解不不够不够.主题说的是 storage时间,说起对 storage 事件的了解还是从 QQ音乐 说起. QQ音乐的主页是 https://y.qq.com , 而 ...

  10. JDBC详解系列(三)之建立连接(DriverManager.getConnection)

      在JDBC详解系列(一)之流程中,我将数据库的连接分解成了六个步骤. JDBC流程: 第一步:加载Driver类,注册数据库驱动: 第二步:通过DriverManager,使用url,用户名和密码 ...