【bzoj4826】[Hnoi2017]影魔 单调栈+可持久化线段树
题目描述
输入
输出
样例输入
10 5 2 3
7 9 5 1 3 10 6 8 2 4
1 7
1 9
1 3
5 9
1 5
样例输出
30
39
4
13
16
题解
单调栈+可持久化线段树
先使用单调栈求出i左边第一个比i大的位置l[i],和右边第一个比i大的位置r[i]。
考虑i对答案的贡献,当且仅当i作为区间[x+1,y-1]的最大值时,i才对点对(x,y)有贡献。
根据题意,第一种情况i产生贡献的点对是(l[i] , r[i]),
第二种情况i产生贡献的点对是(l[i] , i+1~r[i]-1)和(r[i] , l[i]+1~i-1)。
同时还要加上特殊情况(i , i+1)。
问题便转化为在二维平面上,有一些线段被涂色(点算作特殊的包含点数为1的线段),问一个矩形区域内的涂色的点的个数。
可以使用扫描线来解决,然而蒟蒻不会,所以写了主席树。
发现点对的第一个点都是固定的,所以我们可以以第一个点为根建立可持久化线段树,并在对应的可持久化线段树上进行区间更新。
然而可持久化线段树的pushdown比较复杂,所以我使用了标记永久化的方法来完成。
最后查询的矩形是(a,a)与(b,b)之间的部分,查询[a,b]内root[b]与root[a-1]的差即为答案。
#include <cstdio>
#include <algorithm>
#define N 200010
#define lson l , mid , ls[x] , ls[y]
#define rson mid + 1 , r , rs[x] , rs[y]
using namespace std;
typedef long long ll;
struct data
{
int x , l , r;
ll p;
data() {}
data(int x0 , int l0 , int r0 , ll p0) {x = x0 , l = l0 , r = r0 , p = p0;}
}v[N << 2];
int a[N] , lp[N] , rp[N] , sta[N] , top , cnt , root[N] , ls[N << 6] , rs[N << 6] , tot;
ll sum[N << 6] , add[N << 6];
bool cmp(data a , data b)
{
return a.x < b.x;
}
void pushup(int x)
{
sum[x] = sum[ls[x]] + sum[rs[x]];
}
void insert(int b , int e , ll a , int l , int r , int x , int &y)
{
y = ++tot , ls[y] = ls[x] , rs[y] = rs[x] , add[y] = add[x] , sum[y] = sum[x] + a * (e - b + 1);
if(b == l && r == e)
{
add[y] += a;
return;
}
int mid = (l + r) >> 1;
if(e <= mid) insert(b , e , a , lson);
else if(b > mid) insert(b , e , a , rson);
else insert(b , mid , a , lson) , insert(mid + 1 , e , a , rson);
}
ll query(int b , int e , int l , int r , int x , int y)
{
if(b <= l && r <= e) return sum[y] - sum[x];
int mid = (l + r) >> 1;
ll ans = (add[y] - add[x]) * (e - b + 1);
if(e <= mid) return ans + query(b , e , lson);
else if(b > mid) return ans + query(b , e , rson);
else return ans + query(b , mid , lson) + query(mid + 1 , e , rson);
}
int main()
{
int n , m , i , j , x , y;
ll p1 , p2;
scanf("%d%d%lld%lld" , &n , &m , &p1 , &p2);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
a[0] = a[n + 1] = 1 << 30 , top = 1;
for(i = 1 ; i <= n ; i ++ )
{
while(a[sta[top]] < a[i]) top -- ;
lp[i] = sta[top] , sta[++top] = i;
}
top = 1 , sta[1] = n + 1;
for(i = n ; i >= 1 ; i -- )
{
while(a[sta[top]] < a[i]) top -- ;
rp[i] = sta[top] , sta[++top] = i;
}
for(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 , cmp);
for(i = j = 1 ; i <= n ; i ++ )
{
root[i] = root[i - 1];
while(j <= cnt && v[j].x == i)
insert(v[j].l , v[j].r , v[j].p , 1 , n , root[i] , root[i]) , j ++ ;
}
while(m -- )
{
scanf("%d%d" , &x , &y);
printf("%lld\n" , query(x , y , 1 , n , root[x - 1] , root[y]));
}
return 0;
}
【bzoj4826】[Hnoi2017]影魔 单调栈+可持久化线段树的更多相关文章
- BZOJ 4826: [Hnoi2017]影魔 单调栈+可持久化线段树
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样 的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个 ...
- 【bzoj3956】Count 单调栈+可持久化线段树
题目描述 输入 输出 样例输入 3 2 0 2 1 2 1 1 1 3 样例输出 0 3 题解 单调栈+可持久化线段树 本题是 bzoj4826 的弱化版(我为什么做题总喜欢先挑难的做QAQ) $k$ ...
- [BZOJ4826] [HNOI2017] 影魔 单调栈 主席树
题面 因为是一个排列,所以不会有重复的.如果有重复就没法做了.一开始没有仔细看题目想了半天. 发现,如果是第一种情况,那么边界\(l\)和\(r\)就应该分别是整个区间的最大值和次大值. 然后,对于那 ...
- 【BZOJ4826】[Hnoi2017]影魔 单调栈+扫描线
[BZOJ4826][Hnoi2017]影魔 Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝 ...
- BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树
https://www.lydsy.com/JudgeOnline/problem.php?id=4826 年少不知空间贵,相顾mle空流泪. 和上一道主席树求的东西差不多,求两种对 1. max(a ...
- [BZOJ4826][HNOI2017]影魔 可持久化线段树
链接 题意:给你 \(1\) 到 \(n\) 的排列 \(k_1,k_2,\dots,k_n\) ,对 \(i,j (i<j)\)来说,若不存在 \(k_s (i<s<j)\) 大于 ...
- bzoj千题计划196:bzoj4826: [Hnoi2017]影魔
http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...
- 洛谷P3994 Highway(树形DP+斜率优化+可持久化线段树/二分)
有点类似NOI2014购票 首先有方程$f(i)=min\{f(j)+(dep_i-dep_j)*p_i+q_i\}$ 这个显然是可以斜率优化的... $\frac {f(j)-f(k)}{dep_j ...
- Uoj #218. 【UNR #1】火车管理 可持久化线段树+思维
Code: #include<bits/stdc++.h> #define maxn 500005 using namespace std; int n,Q,ty,lastans=0; i ...
随机推荐
- Linux下环境搭建(一)——java、tomcat配置
通过2个周末小憩的时间,终究是把linux环境下的jenkins+gitlab+jmeter框架给弄好了.jenkins的配置系列文章,可以翻看我以前的博文.此次,就将在linux下搭建环境的过程以博 ...
- Android Studio中通过CMake使用NDK并编译自定义库和添加预编译库
Note:这篇文章是基于Android Studio 3.01版本的,NDK是R16. step1:创建一个包含C++的项目 其他默认就可以了. C++ Standard 指定编译库的环境,其中Too ...
- MyEclipse中把java项目打包——含有第三方jar包【转】
也适用于eclipse导出jar. 在将项目打包为jar包时一直出现“ClassNotDefFound”错误,百度了很多解决办法都没有解决.最终找到一个很好的解决办法. 1.打包步骤 (1)右键单击j ...
- CodeForces 219D Choosing Capital for Treeland (树形DP)
题意:给一个树形图,n个节点,n-1条有向边,要求选一个节点作为根,使需要改变方向的边的数目最少.并输出所有可能作为根的点. 思路: 先随便一个点进行DFS,计算将每棵子树的边全部往下时,所需要的费用 ...
- (二)mybaits之ORM模型
前言:为什么还没有进入到mybatis的学习呢?因为mybatis框架的核心思想就是ORM模型,所以好好了解一下ORM模型是有必要哒. ORM模型 ORM(Object Relational Ma ...
- UVA 753 A Plug for UNIX (最大流)
关键在建图,转换器连一条容量无限的边表示可以转化无数次,设备的插头连源点,插座连汇点. dinic手敲已熟练,输出格式又被坑,总结一下,输出空行多case的,一个换行是必要的,最后一个不加空行,有Te ...
- UVA - 658 It's not a Bug, it's a Feature! (隐式图的最短路,位运算)
隐式的图搜索,存不下边,所以只有枚举转移就行了,因为bug的存在状态可以用二进制表示,转移的时候判断合法可以用位运算优化, 二进制pre[i][0]表示可以出现的bug,那么u&pre[i][ ...
- core 下使用 autofac
依赖注入小伙伴们比较常了,这里只说core 下autofac依赖注入的使用 ,不多费话,直接代码. 在 Startup.cs里 public void ConfigureServices(IServi ...
- caffe修改需要的东西
https://blog.csdn.net/zhaishengfu/article/details/51971768?locationNum=3&fps=1
- 数据库_8_SQL基本操作——数据操作
SQL基本操作——数据操作 一.新增数据(两种方案) 方案1: 给全表字段插入数据,不需要指定字段列表,要求数据的值出现的顺序必须与表中设计的字段出现的顺序一致,凡是非数值数据,都需要使用引号(建议是 ...