Description

题库链接

给你一段长度为 \(n\) 的序列 \(K\) 。 \(m\) 组询问,每次给定左右端点 \(l,r\) 。求出满足区间内下述贡献和。

  1. 如果一个区间的两个端点是这一个区间的最大与次大值,那么将获得 \(p_1\) 的价值;
  2. 如果一个区间的一个端点是最大值,而另一个端点不是次大值,那么将获得 \(p_2\) 的价值。

\(1\leq n,m\leq 200000\)

Solution

显然,两种情况都需要满足其中一个端点是最大值。我们可以用单调栈预处理出两个数组 \(l_i,r_i\) 分别表示左边第一个比 \(K_i\) 大的数的位置,以及右边第一个比 \(K_i\) 大的数的位置。

显然我们枚举位置 \(i\) 时,满足:

  1. 左端点为 \(l_i\) 右端点为 \(r_i\) 时,这个区间贡献为 \(p_1\) ;
  2. 左端点为 \(l_i\) 右端点在 \((i,r_i)\) 之间时,贡献为 \(p_2\) ;
  3. 左端点在 \((l_i, i)\) 之间时,右端点为 \(r_i\) ,贡献为 \(p_2\)

然后就是扫描线来处理所有询问了。

因为单调队列的 \(while\) 写成 \(if\) 调了一下午。

Code

//It is made by Awson on 2018.3.6
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 200000; int n, m, p1, p2, a[N+5], l[N+5], r[N+5], S[N+5], top, cnt; LL ans[N+5];
struct Segment_tree {
#define lr(o) (o<<1)
#define rr(o) (o<<1|1)
LL key[(N<<2)+5], lazy[(N<<2)+5];
void pushdown(int o, int l, int r, int mid) {
key[lr(o)] += 1ll*(mid-l+1)*lazy[o];
key[rr(o)] += 1ll*(r-mid)*lazy[o];
lazy[lr(o)] += lazy[o], lazy[rr(o)] += lazy[o];
lazy[o] = 0;
}
void update(int o, int l, int r, int a, int b, int k) {
if (a <= l && r <= b) {key[o] += 1ll*(r-l+1)*k, lazy[o] += k; return; }
int mid = (l+r)>>1; if (lazy[o]) pushdown(o, l, r, mid);
if (a <= mid) update(lr(o), l, mid, a, b, k);
if (b > mid) update(rr(o), mid+1, r, a, b, k);
key[o] = key[lr(o)]+key[rr(o)];
}
LL query(int o, int l, int r, int a, int b) {
if (a <= l && r <= b) return key[o]; int mid = (l+r)>>1;
if (lazy[o]) pushdown(o, l, r, mid); LL c1 = 0, c2 = 0;
if (a <= mid) c1 = query(lr(o), l, mid, a, b);
if (b > mid) c2 = query(rr(o), mid+1, r, a, b);
return c1+c2;
}
}T;
struct opts {
int l, r, t, id, p;
bool operator < (const opts &b) const {return t < b.t; }
}s1[N*2+5], s2[N*3+5]; void work() {
scanf("%d%d%d%d", &n, &m, &p1, &p2);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) {
int l, r;
scanf("%d%d", &l, &r); ans[i] = 1ll*(r-l)*p1;
s1[i].l = l, s1[i].r = r, s1[i].t = l-1, s1[i].id = i, s1[i].p = -1;
s1[i+m].l = l, s1[i+m].r = r, s1[i+m].t = r, s1[i+m].id = i, s1[i+m].p = 1;
}
top = 0;
for (int i = 1; i <= n; i++) {
while (top > 0 && a[i] > a[S[top]]) --top;
l[i] = (top == 0 ? 0 : S[top]); S[++top] = i;
}
top = 0;
for (int i = n; i >= 1; i--) {
while (top > 0 && a[i] > a[S[top]]) --top;
r[i] = top == 0 ? n+1 : S[top]; S[++top] = i;
}
for (int i = 1; i <= n; i++) {
if (l[i] != 0 && r[i] != n+1) s2[++cnt].l = s2[cnt].r = r[i], s2[cnt].t = l[i], s2[cnt].p = p1;
if (l[i] != 0 && r[i] > i+1) s2[++cnt].l = i+1, s2[cnt].r = r[i]-1, s2[cnt].t = l[i], s2[cnt].p = p2;
if (l[i] < i-1 && r[i] != n+1) s2[++cnt].l = l[i]+1, s2[cnt].r = i-1, s2[cnt].t = r[i], s2[cnt].p = p2;
}
sort(s1+1, s1+2*m+1); sort(s2+1, s2+cnt+1);
int n1 = 1, n2 = 1;
while (n1 <= 2*m) {
while (n2 <= cnt && s2[n2].t <= s1[n1].t) T.update(1, 1, n, s2[n2].l, s2[n2].r, s2[n2].p), ++n2;
while (n1 <= 2*m && (s1[n1].t < s2[n2].t || n2 > cnt)) ans[s1[n1].id] += 1ll*T.query(1, 1, n, s1[n1].l, s1[n1].r)*s1[n1].p, ++n1;
}
for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]);
}
int main() {
work(); return 0;
}

[HNOI 2017]影魔的更多相关文章

  1. [HNOI/AHOI2017]影魔

    [HNOI/AHOI2017]影魔 题目大意: 有一排\(n(n\le2\times10^5)\)个数\(k_{1\sim n}\).对于点对\((i,j)\),若不存在\(k_s(i<s< ...

  2. 【HNOI 2017】影魔

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

  3. [HNOI 2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的 ...

  4. [HNOI 2017]抛硬币

    Description 题库链接 两人抛硬币一人 \(a\) 次,一人 \(b\) 次.记正面朝上多的为胜.问抛出 \(a\) 次的人胜出的方案数. \(1\le a,b\le 10^{15},b\l ...

  5. [HNOI 2017]礼物

    Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在 ...

  6. 【HNOI 2017】大佬

    Problem Description 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语.你作为一个 OIer, ...

  7. HNOI 2017

    题目链接 我还是按bzoj AC数量排序做的 4827 这个其实如果推一下(求每个值)式子会发现是个卷积,然后FFT就好了 4826 记不太清了,可以求出每个点左右第一个比他的的点的位置,将点对看成平 ...

  8. 【HNOI 2017】礼物

    Problem Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她.每个手环上各有 \(n\) 个装饰物,并且每个装饰物 ...

  9. [HNOI 2017]大佬

    Description 题库链接 题意简述来自Gypsophila. 你现在要怼 \(m\) 个大佬,第 \(i\) 个大佬的自信值是 \(C_i\) .每次怼大佬之前,你的自信值是 \(mc\),等 ...

随机推荐

  1. MySQL的学习记录(3.31更新)

    MySQL的学习记录(3.31更新) 0x00 安装及配置 Windows 1.首先官网下载(https://dev.mysql.com/downloads/mysql/) ps:不想官网下载的可以到 ...

  2. MongoDB系列三(Spring集成方案).

    一.前言 MongoDB是最为流行的开源文档数据库之一.Spring Data MongoDB提供了三种方式在Spring应用中使用MongoDB: 通过注解实现对象-文档映射: 使用MongoTem ...

  3. 网络推广 免费推广产品网站 B2B网站如何推广

    云集网(yunjinet.com)免费发布各类服务和产品信息,在平台上推广你的产品.帮助商家推广优质的产品和服务.如何提高信息的点击量为了提高分类信息网的信息质量,对重复度高.相似度高的信息进行了过滤 ...

  4. 第四次团队作业:社团申请App

    概要: 基于上次软件设计本着界面简洁.易于使用的初衷,进行功能的实现,代码位置:https://github.com/LinZezhong/testDemo 第一部分:软件的使用 注册: 登录: 主界 ...

  5. 201621123057 《Java程序设计》第8周学习总结

    1. 本周学习总结 思维导图归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 ArrayList是允许重复的,但当用它来 ...

  6. 第201621123043 《Java程序设计》第13周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 系统还在创建中..... 为了让你 ...

  7. iOS开发UIKit框架-可视化编程-XIB

    1. Interface Builder 可视化编程 1> 概述 GUI : 图形用户界面(Graphical User Interface, 简称GUI, 又称图形化界面) 是指采用图形方式显 ...

  8. 用virtualenv建立多个Python独立开发环境

    不同的人喜欢用不同的方式建立各自的开发环境,但在几乎所有的编程社区,总有一个(或一个以上)开发环境让人更容易接受. 使用不同的开发环境虽然没有什么错误,但有些环境设置更容易进行便利的测试,并做一些重复 ...

  9. 如何使用ILAsm与ILDasm修改.Net exe(dll)文件

    一.背景 最近项目组新上项目,交付的时间比较急迫,原本好的分支管理习惯没有遵守好,于是出现下面状况: 多个小伙伴在不同的分支上开发. 原本QA环境也存在一个阻碍性的bug A 一位同事在QA环境发布了 ...

  10. JDBC操作数据库的三种方式比较

    JDBC(java Database Connectivity)java数据库连接,是一种用于执行上sql语句的javaAPI,可以为多种关系型数据库提供统一访问接口.我们项目中经常用到的MySQL. ...