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. 20162302 实验四《Android程序设计》实验报告

    实 验 报 告 课程:程序设计与数据结构 姓名:杨京典 班级:1623 学号:20162302 实验名称:Android程序设计 实验器材:装有Android Studio的联想拯救者80RQ 实验目 ...

  2. Vim 中文社区:期待你的加入

    我们的愿景 Vim 中文社区一直比较零散,缺少凝聚力,现有的一些群经常也是水的可以的,讨论各种无关紧要的内容,于是导致很大一部分人,将这些群丢入了群助手,渐渐地他们也淡出了 vim 中文社区. 而我理 ...

  3. Ubuntu命令行连接WPA/WPA2无线网线

    一,连接无加密无线网络zhang:sudo ip link set wlan0 up sudo iw dev wlan0 connect zhangsudo dhclient wlan0 二,连接WP ...

  4. OpenShift实战(三):OpenShift持久化存储Redis

    1.模板定义 修改OpenShift自带模板 [root@master1 pv]# oc edit template redis-persistent 添加如下: 2.创建PV 编辑redis pv ...

  5. PHP常用函数集合

    PHP常用函数总结 数学函数 1.abs(): 求绝对值 $abs = abs(-4.2); //4.2 数字绝对值数字 2.ceil(): 进一法取整 echo ceil(9.999); // 10 ...

  6. keycloak管理用户权限

    一.在keycloak中定义基础数据 1.realm 如果多个模块使用不同的用户权限,就分realm 如果多个模块共用一套用户权限,就顶一个一个realm 2.每个模块是一个client-app 3. ...

  7. Docker加速器(阿里云)

    1. 登录阿里开发者平台: https://dev.aliyun.com/search.html,https://cr.console.aliyun.com/#/accelerator,生成专属链接 ...

  8. 阿里云API网关(15)监控预警

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  9. nodejs调试总结

    之前nodejs开发中最痛苦的就是调试,因为我之前开发node时使用的编辑器还没有将nodejs的调试也集成进去,所以简单对nodejs开发的调试做了点探索,nodejs本身就有调试功能,同时node ...

  10. python爬虫requests的使用

    1 发送get请求获取页面 import requests # 1 要爬取的页面地址 url = 'http://www.baidu.com' # 2 发送get请求 拿到响应 response = ...