首先用单调栈和扫描线处理出每一个数左面最近的比他大的数在$l[i]$,右面最近的比他大的数$r[i]$。

然后就可以考虑每种贡献是在什么时候产生的。

1、$(l[i],r[i])$产生$p1$的贡献

2、$([l[i]]-[i-1],i)$产生$p2$的贡献

3、$(i,[i+1]-[r[i]])$产生$p2$的贡献。

然后发现在笛卡尔坐标系中是一些线段和点,然后平行与扫描线的比较好解决。

但是垂直的就比较麻烦了。

然后有人用六棵主席树做过去了,也有人用四棵。

其实只要线段树分两次扫一遍就好了。

#include <map>
#include <ctime>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define maxn 200005 struct Options{
int opt; //1 add 0 query
int x,y,z,d,id;
Options() {}
Options(int _opt,int _x,int _y,int _z,int _d)
{opt=_opt;x=_x;y=_y;z=_z;d=_d;}
void print()
{
printf("Opt %d ( %d , %d , %d ) ID %d D: %d\n",opt,x,y,z,id,d);
}
}q[maxn<<3]; int n,m,p1,p2,a[maxn],cnt=0,sta[maxn],top,l[maxn],r[maxn],_l[maxn],_r[maxn];
ll ans[maxn],sum[maxn<<3],mark[maxn<<3]; bool cmp1(Options a,Options b)
{return a.x==b.x?a.opt>b.opt:a.x<b.x;}
bool cmp2(Options a,Options b)
{return a.y==b.y?a.opt>b.opt:a.y<b.y;} void update(int o)
{sum[o]=sum[o<<1]+sum[o<<1|1];} void pushdown(int o,int l,int r)
{
if (mark[o]!=0)
{
int mid=l+r>>1;
sum[o<<1]+=(mid-l+1)*mark[o];
sum[o<<1|1]+=(r-mid)*mark[o];
mark[o<<1]+=mark[o];
mark[o<<1|1]+=mark[o];
mark[o]=0;
}
} void modify(int o,int l,int r,int L,int R,int f)
{
if (L<=l&&r<=R)
{
mark[o]+=f;
sum[o]+=(r-l+1)*f;
return;
}
int mid=l+r>>1;pushdown(o,l,r);
if (L<=mid) modify(o<<1,l,mid,L,R,f);
if (R>mid) modify(o<<1|1,mid+1,r,L,R,f);
update(o);
} ll query(int o,int l,int r,int L,int R)
{
if (L<=l&&r<=R) return sum[o];
int mid=l+r>>1;pushdown(o,l,r);
if (R<=mid) return query(o<<1,l,mid,L,R);
if (L>mid) return query(o<<1|1,mid+1,r,L,R);
return query(o<<1,l,mid,L,R)+query(o<<1|1,mid+1,r,L,R);
} int main()
{
scanf("%d%d%d%d",&n,&m,&p1,&p2);
F(i,1,n) scanf("%d",&a[i]);
F(i,1,m)
{
int x,y; scanf("%d%d",&_l[i],&_r[i]); x=_l[i];y=_r[i];
q[++cnt].id=i;q[cnt].d=1; q[cnt].x=y+1;q[cnt].y=y+1;q[cnt].opt=0;
q[++cnt].id=i;q[cnt].d=1; q[cnt].x=x; q[cnt].y=x; q[cnt].opt=0;
q[++cnt].id=i;q[cnt].d=-1;q[cnt].x=x; q[cnt].y=y+1;q[cnt].opt=0;
q[++cnt].id=i;q[cnt].d=-1;q[cnt].x=y+1;q[cnt].y=x; q[cnt].opt=0;
}
F(i,1,n)
{
while(top&&a[sta[top]]<a[i]) top--;
l[i]=sta[top];
sta[++top]=i;
}
sta[top=0]=n+1;
D(i,n,1)
{
while(top&&a[sta[top]]<a[i]) top--;
r[i]=sta[top];
sta[++top]=i;
}
F(i,1,n-1)
{
q[++cnt].opt=1;q[cnt].x=i+1;q[cnt].y=i+2;q[cnt].z=i+2;q[cnt].d=p1;
}
F(i,1,n)
{
q[++cnt]=Options(1,l[i]+1,r[i]+1,r[i]+1,p1);
if (r[i]-1>=i+1) q[++cnt]=Options(1,l[i]+1,i+2,r[i],p2);
}
sort(q+1,q+cnt+1,cmp1);
F(i,1,cnt)
{
switch(q[i].opt)
{
case 0:ans[q[i].id]+=q[i].d*query(1,1,n+2,1,q[i].y);break;
case 1:modify(1,1,n+2,q[i].y,q[i].z,q[i].d);break;
}
}
memset(sum,0,sizeof sum); memset(mark,0,sizeof mark);cnt=0;
F(i,1,m)
{
int x,y;x=_l[i];y=_r[i];
q[++cnt].id=i;q[cnt].d=1; q[cnt].x=y+1;q[cnt].y=y+1;q[cnt].opt=0;
q[++cnt].id=i;q[cnt].d=1; q[cnt].x=x; q[cnt].y=x; q[cnt].opt=0;
q[++cnt].id=i;q[cnt].d=-1;q[cnt].x=x; q[cnt].y=y+1;q[cnt].opt=0;
q[++cnt].id=i;q[cnt].d=-1;q[cnt].x=y+1;q[cnt].y=x; q[cnt].opt=0;
}
F(i,1,n) if (l[i]+1<=i-1) q[++cnt]=Options(1,l[i]+2,r[i]+1,i,p2);
sort(q+1,q+cnt+1,cmp2);
F(i,1,cnt)
{
switch(q[i].opt)
{
case 0:ans[q[i].id]+=q[i].d*query(1,1,n+2,1,q[i].x);break;
case 1:modify(1,1,n+2,q[i].x,q[i].z,q[i].d);break;
}
}
F(i,1,m) printf("%lld\n",ans[i]);
}

  

BZOJ 4826 [Hnoi2017]影魔 ——扫描线 单调栈的更多相关文章

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

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

  2. bzoj 4826: [Hnoi2017]影魔 [主席树 单调栈]

    4826: [Hnoi2017]影魔 题意:一个排列,点对\((i,j)\),\(p=max(i+1,j-1)\),若\(p<a_i,a_j\)贡献p1,若\(p\)在\(a_1,a_2\)之间 ...

  3. BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树

    https://www.lydsy.com/JudgeOnline/problem.php?id=4826 年少不知空间贵,相顾mle空流泪. 和上一道主席树求的东西差不多,求两种对 1. max(a ...

  4. BZOJ 4826: [Hnoi2017]影魔 单调栈+可持久化线段树

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

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

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

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

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

  7. ●BZOJ 4826 [Hnoi2017]影魔

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4826 题解: 主席树,单调栈 以前还没做过这种维护信息的题,感觉好奇妙. 每对相邻的两个数所 ...

  8. BZOJ:4826: [Hnoi2017]影魔

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

  9. 4826: [Hnoi2017]影魔

    4826: [Hnoi2017]影魔 https://lydsy.com/JudgeOnline/problem.php?id=4826 分析: 莫队+单调栈+st表. 考虑如何O(1)加入一个点,删 ...

随机推荐

  1. Python 之继承

    概要 如果要修改现有类的行为,我们不必再从头建一个新的类,可以直接利用继承这一功能.下面将以实例相结合介绍继承的用法.   新建一个基类 代码如下: class Marvel(object): num ...

  2. 【wiki】红帽linux

    Red Hat Enterprise Linux From Wikipedia, the free encyclopedia wiki 上面红帽的版本信息. https://en.wikipedia. ...

  3. javaweb基础(34)_jdbc处理mysql大数据

    一.基本概念 大数据也称之为LOB(Large Objects),LOB又分为:clob和blob,clob用于存储大文本,blob用于存储二进制数据,例如图像.声音.二进制文等. 在实际开发中,有时 ...

  4. 按格式读取csv文件内容

    string path = @"C:\Users\keen_\Downloads\upload\upload\Upload\20140701141934_export.csv"; ...

  5. Xcode Warning: “no rule to process file

    警告⚠️: warning: no rule to process file '/Users/Kingdev/Desktop/Git/finance_iOS/finance/Library/MBpro ...

  6. BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)

    题意 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G' ...

  7. SAP事件 Event Flow(转载)

    1 报表过程事件 报表过程事件是在报表运行过程中由系统自动控制,按照一定次序被触发的事件,其目的是从数据库中选择数据并整理,准备进行列表输出.这些事件从报表程序启动开始就被系统顺序触发,现分述如下: ...

  8. Freemaker基于word模板动态导出压缩文件汇总整理

    Freemaker基于word模板动态导出压缩文件汇总整理 Freemaker基于word模板动态导出单个文件思路和代码详情见连接: https://www.cnblogs.com/lsy-blogs ...

  9. js字符串去掉所有空格

    字符串去掉所有空格 "abc 123 def".replace(/\s/g, "") 字符串去掉左右两端空格 " abc 123 def " ...

  10. pycharm配置Git托管

    利用Pycharm和github管理代码转载https://www.cnblogs.com/feixuelove1009/p/5955332.html git教程--廖雪峰git教程  转载https ...