【LG3722】[HNOI2017]影魔
【LG3722】[HNOI2017]影魔
题面
题解
先使用单调栈求出\(i\)左边第一个比\(i\)大的位置\(lp_i\),和右边第一个比\(i\)大的位置\(rp_i\)。
考虑\(i\)对答案的贡献,当且仅当\(i\)作为区间\([x+1,y-1]\)的最大值时,\(i\)才对点对\((x,y)\)有贡献。
根据题意,第一种情况\(i\)产生贡献的点对是\((lp_i,rp_i)\),
第二种情况\(i\)产生贡献的点对是\((l[i],i+1\) to \(r[i]-1)\)和\((r[i],l[i]+1\) to \(i-1)\)。
同时还要加上特殊情况\((i,i+1)\)。
问题便转化为在二维平面上,有一些线段被涂色(点算作特殊的包含点数为1的线段),问一个矩形区域内的涂色的点的个数。
常用做法是扫描线,但是我写的是主席树。
发现点对的第一个点都是固定的,所以我们可以以第一个点为根建立可持久化线段树,并在对应的可持久化线段树上进行区间更新,并且标记永久化即可。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (ch != '-' && (ch > '9' || ch < '0')) ch = getchar();
if (ch == '-') w = -1 , ch = getchar();
while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
return w * data;
}
typedef long long ll;
#define MAX_N 200005
int N, M, P1, P2, a[MAX_N];
int st[MAX_N], top, lp[MAX_N], rp[MAX_N];
struct data {
int x, l, r;
ll p;
data() {}
data(int _x, int _l, int _r, ll _p) { l = _l, r = _r, x = _x, p = _p; }
bool operator < (const data &rhs) const {
return x < rhs.x;
}
} v[MAX_N << 2];
int cnt = 0;
struct Node {
int ls, rs;
ll s, tag;
} t[MAX_N << 6];
int rt[MAX_N], tot;
void build(int &x, int l, int r) {
x = ++tot;
if (l == r) return ;
int mid = (l + r) >> 1;
build(t[x].ls, l, mid); build(t[x].rs, mid + 1, r);
}
void insert(int &x, int y, int l, int r, int ql, int qr, ll v) {
x = ++tot; t[x] = t[y]; t[x].s = t[y].s + (qr - ql + 1) * v;
if (ql == l && r == qr) { t[x].tag += v; return ; }
int mid = (l + r) >> 1;
if (qr <= mid) insert(t[x].ls, t[y].ls, l, mid, ql, qr, v);
else if (ql > mid) insert(t[x].rs, t[y].rs, mid + 1, r, ql, qr, v);
else insert(t[x].ls, t[y].ls, l, mid, ql, mid, v), insert(t[x].rs, t[y].rs, mid + 1, r, mid + 1, qr, v);
}
ll query(int u, int v, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return t[u].s - t[v].s;
int mid = (l + r) >> 1;
ll res = (t[u].tag - t[v].tag) * (qr - ql + 1);
if (qr <= mid) return query(t[u].ls, t[v].ls, l, mid, ql, qr) + res;
else if (ql > mid) return query(t[u].rs, t[v].rs, mid + 1, r, ql, qr) + res;
else return res + query(t[u].ls, t[v].ls, l, mid, ql, mid) + query(t[u].rs, t[v].rs, mid + 1, r, mid + 1, qr);
}
int main () {
N = gi(), M = gi(), P1 = gi(), P2 = gi();
for (int i = 1; i <= N; i++) a[i] = gi();
top = 0;
for (int i = 1; i <= N; i++) {
while (top && a[st[top]] < a[i]) --top;
lp[i] = st[top], st[++top] = i;
}
top = 0;
for (int i = N; i >= 1; i--) {
while (top && a[st[top]] < a[i]) --top;
rp[i] = top ? st[top] : (1 + N), st[++top] = i;
}
for (int i = 1; i <= N; i++) {
if (lp[i] != 0 && rp[i] != N + 1) v[++cnt] = data(lp[i], rp[i], rp[i], P1);
if (i < N) v[++cnt] = data(i, i + 1, i + 1, P1);
if (lp[i] != 0 && rp[i] - i > 1) v[++cnt] = data(lp[i], i + 1, rp[i] - 1, P2);
if (rp[i] != N + 1 && i - lp[i] > 1) v[++cnt] = data(rp[i], lp[i] + 1, i - 1, P2);
}
sort(&v[1], &v[cnt + 1]);
build(rt[0], 1, N);
for (int i = 1, j = 1; i <= N; i++) {
rt[i] = rt[i - 1];
while (j <= cnt && v[j].x == i)
insert(rt[i], rt[i], 1, N, v[j].l, v[j].r, v[j].p), j++;
}
while (M--) {
int l = gi(), r = gi();
printf("%lld\n", query(rt[r], rt[l - 1], 1, N, l, r));
}
return 0;
}
【LG3722】[HNOI2017]影魔的更多相关文章
- bzoj 4826: [Hnoi2017]影魔 [主席树 单调栈]
4826: [Hnoi2017]影魔 题意:一个排列,点对\((i,j)\),\(p=max(i+1,j-1)\),若\(p<a_i,a_j\)贡献p1,若\(p\)在\(a_1,a_2\)之间 ...
- 4826: [Hnoi2017]影魔
4826: [Hnoi2017]影魔 https://lydsy.com/JudgeOnline/problem.php?id=4826 分析: 莫队+单调栈+st表. 考虑如何O(1)加入一个点,删 ...
- [BZOJ4826][HNOI2017]影魔(主席树)
4826: [Hnoi2017]影魔 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 669 Solved: 384[Submit][Status][ ...
- 【BZOJ4826】[Hnoi2017]影魔 单调栈+扫描线
[BZOJ4826][Hnoi2017]影魔 Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝 ...
- [bzoj4826][Hnoi2017]影魔_单调栈_主席树
影魔 bzoj-4826 Hnoi-2017 题目大意:给定一个$n$个数的序列$a$,求满足一下情况的点对个数: 注释:$1\le n,m\le 2\cdot 10^5$,$1\le p1,p2\l ...
- bzoj4826 [Hnoi2017]影魔
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...
- BZOJ:4826: [Hnoi2017]影魔
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...
- [AH/HNOI2017]影魔
题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂. 事实上,他吞噬的诗人灵魂早已成千上万. 千百年来,他收集了各式各样的灵魂,包括诗人. 牧师. 帝王. 乞丐. 奴隶. 罪人,当然,还有英雄. 题目描 ...
- HNOI2017影魔
影魔 这么简单的方法尽然想不到,我是真的菜 对每个点,用单调栈的方式处理出他左右第一个比他大的数的位置,你可以把\(0\)和\(n+1\)设成\(inf\). 显然对于每对\(lef[i]\)和\(r ...
随机推荐
- java vector的多线程安全是否有用
在网上搜了不少文章,发现有不少没讲清楚的,也有不少好文,本文希望更易懂地描述该问题.如有不对的地方,请多多指正~~ vector的使用主要有如下两种场景:(1)vector所谓的多线程安全,只是针对单 ...
- 修改UIView的默认Layer后,修改View的值会动态修改Layer的值
修改UIView的默认Layer后,修改View的值会动态修改Layer的值 效果图: 如上图所示,当我们修改了一个UIView的子类中的Layer内置类型时(如上图中我们将CALayer直接替换成了 ...
- 如何生成.mobileprovision文件
如何生成.mobileprovision文件 本人视频教程系列 **.mobileprovision文件的生成的第一步就需要你提供一个用于开发的App ID 1. 创建App ID 创建一个bundl ...
- apache的AllowOverride以及Options使用详解
通常利用Apache的rewrite模块对 URL 进行重写的时候, rewrite规则会写在 .htaccess 文件里.但要使 apache 能够正常的读取.htaccess 文件的内容,就必须对 ...
- windows下PyCharm安装及使用
一.首先安装pycharm,可以参考这篇文章:http://www.jianshu.com/p/042324342bf4 1.win10_X64,其他Win版本也可以. 2.PyCharm版本:Pro ...
- JS代码高亮编辑器 ace.js
JS代码高亮编辑器 ace.js 字数254 阅读2 评论0 喜欢0 瞎扯 ace 是 js 实现的代码编辑器 编译打包之后的 ACE 代码 官网,未提供编译好的文件 ACE 拥有的特点 语法高亮超过 ...
- 囧啊!!时间戳转化为时间出错php
最近写了一个api,测试也没发现啥问题.可是上线之后发现有时api的返回结果不正确.为什么呢? 调我接口的同学给了两个调用示例,理论上两个的结果应该一致,实际结果却不一致. api调用带了一个时间戳参 ...
- echarts中datazoom相关配置
dataZoom=[ //区域缩放 { id: 'dataZoomX', show:true, //是否显示 组件.如果设置为 false,不会显示,但是数据过滤的功能还存在. backgroundC ...
- 基于easyui开发Web版Activiti流程定制器详解(五)——Draw2d详解(一)
背景: 小弟工作已有十年有余,期间接触了不少工作流产品,个人比较喜欢的还是JBPM,因为出自名门Jboss所以备受推崇,但是现在JBPM版本已经与自己当年使用的版本(3.X)大相径庭,想升级也不太容易 ...
- Python - 格式化字符串的用法
0. 摘要 Python支持多种格式化字符串的方法,包括%-fromatting.str.format().f-strings三种,f-strings是Python3.6以后出现的一种新方法,相比其他 ...