【BZOJ4826】【HNOI2017】影魔(扫描线,单调栈)

题面

BZOJ

洛谷

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

题解

这题和序列很类似

但是我依然不是自己做出来的

还是太弱了


首先把两种贡献换成人话:

如果对于两个位置\(l,r\)

他们是区间\([l,r]\)中的最大值和次大值,产生\(p1\)的贡献

如果恰好有一个是最大值,产生\(p2\)的贡献

那么,对于当前位置\(i\),假设左/右第一个比他大的位置是\(l,r\)

那么,\((l,r)\)产生\(p1\)的贡献

\((l+1..i-1,r),(l,i+1..r-1)\)会产生\(p2\)的贡献

可以把他分解为二维平面内的矩阵求和问题,这个可以用扫描线来解决

当然,主要的问题是怎么转换为二维平面求矩阵和。。。

我们算的是当前加上了位置\(i\)以后产生的贡献

如果对于一个询问\(L,R\),\(i\)在其范围内,当然就要考虑它产生的贡献

那么,\(i\)产生的贡献是什么?

就是我们前面考虑过的问题

将一个位置\(i\)拆分成\(3\)个贡献:

当加入完位置\(R[i]\)之后,要对于\(L[i]\)产生\(p1\)的贡献

当加入完位置\(L[i]\)之后,要对于\((i,R[i])\)的每个位置产生\(p2\)的贡献

当加入完位置\(R[i]\)之后,要对于\((L[i],i)\)的每个位置产生\(p2\)的贡献

那么,一个询问\(L,R\),只要考虑它范围内的贡献

因此拆分成三部分

加入完\(L-1\)位置之后,要忽略掉前面所有\(L,R\)位置产生的贡献

加入完\(R\)位置之后,要考虑所有的\(L,R\)位置产生的贡献

额外考虑每一组范围内的,\((i,i+1)\)产生的贡献\(p1\)

这样子,扫描线+区间加法+区间求和即可

可以用单调栈+树状数组实现。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 222222
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int L[MAX],R[MAX];
int a[MAX],n,m,p1,p2;
int S[MAX],top,cnt,tot;
struct Line{int x,l,r,v;}p[MAX<<2];
bool operator<(Line a,Line b){return a.x<b.x;}
struct query{int x,l,r,v,id;}q[MAX<<2];
bool operator<(query a,query b){return a.x<b.x;}
ll c1[MAX],c2[MAX],ans[MAX];
void Modify(int x,int w)
{
for(int i=x;i<=n;i+=i&(-i))
c1[i]+=w,c2[i]+=x*w;
}
ll Query(int x)
{
ll ret=0;
for(int i=x;i;i-=i&(-i))
ret+=(x+1)*c1[i]-c2[i];
return ret;
}
int main()
{
n=read();m=read();p1=read();p2=read();
for(int i=1;i<=n;++i)a[i]=read();
S[top=0]=0;
for(int i=1;i<=n;++i)
{
while(top&&a[S[top]]<a[i])--top;
L[i]=S[top];S[++top]=i;
}
S[top=0]=n+1;
for(int i=n;i>=1;--i)
{
while(top&&a[S[top]]<a[i])--top;
R[i]=S[top];S[++top]=i;
}
for(int i=1;i<=m;++i)
{
int l=read(),r=read();ans[i]=(r-l)*p1;
q[++cnt]=(query){r,l,r,1,i};
q[++cnt]=(query){l-1,l,r,-1,i};
}
sort(&q[1],&q[cnt+1]);
for(int i=1;i<=n;++i)
{
if(L[i]&&R[i]<n+1)p[++tot]=(Line){R[i],L[i],L[i],p1};
if(L[i]&&R[i]>i+1)p[++tot]=(Line){L[i],i+1,R[i]-1,p2};
if(L[i]+1<i&&R[i]<n+1)p[++tot]=(Line){R[i],L[i]+1,i-1,p2};
}
sort(&p[1],&p[tot+1]);
for(int i=1,j=1;i<=cnt;++i)
{
while(j<=tot&&p[j].x<=q[i].x)
{
Modify(p[j].l,p[j].v);
Modify(p[j].r+1,-p[j].v);
++j;
}
ans[q[i].id]+=q[i].v*(Query(q[i].r)-Query(q[i].l-1));
}
for(int i=1;i<=m;++i)printf("%lld\n",ans[i]);
return 0;
}

【BZOJ4826】【HNOI2017】影魔(扫描线,单调栈)的更多相关文章

  1. [bzoj4826][Hnoi2017]影魔_单调栈_主席树

    影魔 bzoj-4826 Hnoi-2017 题目大意:给定一个$n$个数的序列$a$,求满足一下情况的点对个数: 注释:$1\le n,m\le 2\cdot 10^5$,$1\le p1,p2\l ...

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

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

  3. P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)

    题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...

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

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

  5. [BZOJ4826] [HNOI2017] 影魔 单调栈 主席树

    题面 因为是一个排列,所以不会有重复的.如果有重复就没法做了.一开始没有仔细看题目想了半天. 发现,如果是第一种情况,那么边界\(l\)和\(r\)就应该分别是整个区间的最大值和次大值. 然后,对于那 ...

  6. bzoj4826 [Hnoi2017]影魔

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

  7. [JXOI2017]颜色 线段树扫描线 + 单调栈

    ---题面--- 题解: 首先题目要求删除一些颜色,换个说法就是要求保留一些颜色,那么观察到,如果我们设ll[i]和rr[i]分别表示颜色i出现的最左边的那个点和最右边的那个点,那么题目就是在要求我们 ...

  8. [BZOJ4826][HNOI2017]影魔 可持久化线段树

    链接 题意:给你 \(1\) 到 \(n\) 的排列 \(k_1,k_2,\dots,k_n\) ,对 \(i,j (i<j)\)来说,若不存在 \(k_s (i<s<j)\) 大于 ...

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

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

  10. BZOJ4826 [Hnoi2017]影魔 【线段树 + 单调栈】

    题目链接 BZOJ4826 题解 蒟蒻智力水平捉急orz 我们会发现相邻的\(i\)和\(j\)贡献一定是\(p1\),可以很快算出来[然而我一开始忘了考虑调了半天] 我们现在只考虑不相邻的 我们只需 ...

随机推荐

  1. html 佈局

    html常見佈局方式有以下幾種: 1.使用div的html 利用div可以為html實現多列佈局. 2.使用html5的網站佈局, 利用html新增的header.footer.nav.section ...

  2. 一本通1609【例 4】Cats Transport

    1609:[例 4]Cats Transport 时间限制: 1000 ms         内存限制: 524288 KB sol:非常偷懒的截图了事 注意:只能猫等人,不能人等猫 对于每只猫,我们 ...

  3. poj3061(尺取法)

    ---恢复内容开始--- 题目意思:给你一段非负序列,再给你一个值k,找出这段序列中最少的连续子序列使得和为k: 解题思路:因为都是正数,我们只需要找到一段区间不大于k,就停止,然后左边趋近看是否能得 ...

  4. BZOJ1131[POI2008]Sta——树形DP

    题目描述 给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大 输入 给出一个数字N,代表有N个点.N<=1000000 下面N-1条边. 输出 输出你所找到的点,如果具有 ...

  5. ACG图片站\python爬虫\LAMP环境

    最近突然对web很感兴趣,碰巧看到阿里云服务器学生价十块钱一个月,果断买了一个自己搭建了一个网站. 网址 这里 LAMP环境就搭建了好久,linux+apache2+mysql+php,都是开源的软件 ...

  6. Cuba项目配置IDEA,如何dubug

    1.在cuba中编辑端口,如下图: 2.在IDEA中添加一个远程链接,添加为对应的端口号,然后运行debug即可 如果两个端口号不对应,就会报出以下的错误:unable to open debugge ...

  7. Luogu 4294 [WC2008]游览计划 | 斯坦纳树

    题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...

  8. Codeforces Round #548

    没打,简单补档 C.Edgy Trees 容斥,把黑边断掉数联通块,每个联通块贡献$siz^k$ #include<cstdio> #include<cstring> #inc ...

  9. property(四十)

    一个静态属性property本质就是实现了get,set,delete三种方法 用法: class Foo: @property def AAA(self): print('get的时候运行我啊') ...

  10. python数据类型(二)

    跟着慕课网练习的,一些简单的知识点如下