BZOJ 4826 [Hnoi2017]影魔 ——扫描线 单调栈
首先用单调栈和扫描线处理出每一个数左面最近的比他大的数在$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]影魔 ——扫描线 单调栈的更多相关文章
- bzoj 4826: [Hnoi2017]影魔【单调栈+树状数组+扫描线】
参考:https://www.cnblogs.com/lcf-2000/p/6789680.html 这是一个相对码量少的做法,用到了区间修改区间查询的树状数组,详见:www.cnblogs.com/ ...
- bzoj 4826: [Hnoi2017]影魔 [主席树 单调栈]
4826: [Hnoi2017]影魔 题意:一个排列,点对\((i,j)\),\(p=max(i+1,j-1)\),若\(p<a_i,a_j\)贡献p1,若\(p\)在\(a_1,a_2\)之间 ...
- BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树
https://www.lydsy.com/JudgeOnline/problem.php?id=4826 年少不知空间贵,相顾mle空流泪. 和上一道主席树求的东西差不多,求两种对 1. max(a ...
- BZOJ 4826: [Hnoi2017]影魔 单调栈+可持久化线段树
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样 的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个 ...
- P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)
题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...
- [bzoj4826][Hnoi2017]影魔_单调栈_主席树
影魔 bzoj-4826 Hnoi-2017 题目大意:给定一个$n$个数的序列$a$,求满足一下情况的点对个数: 注释:$1\le n,m\le 2\cdot 10^5$,$1\le p1,p2\l ...
- ●BZOJ 4826 [Hnoi2017]影魔
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4826 题解: 主席树,单调栈 以前还没做过这种维护信息的题,感觉好奇妙. 每对相邻的两个数所 ...
- BZOJ:4826: [Hnoi2017]影魔
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...
- 4826: [Hnoi2017]影魔
4826: [Hnoi2017]影魔 https://lydsy.com/JudgeOnline/problem.php?id=4826 分析: 莫队+单调栈+st表. 考虑如何O(1)加入一个点,删 ...
随机推荐
- 2017.12.17 servlet 生命周期
servlet生命周期一般分为4个: 加载----实例化------服务-----销毁 (1)加载: 加载一般是在运行tomcat容器时来完成,将servlet类加载到tomcat中,或者是客户端发来 ...
- Shell重启Tomcat脚本
#!/bin/bash echo -e "\n\n\n" #force kill flag,if equal [f] to force kill all flag="He ...
- 重温 JSP 与 Servlet
Java Web使用SSH框架多了,很多基础的 JSP 与 Servlet 的东西都忘记了.最近在 JSP 标签 和 Struts2 包装的 Session 对象的混合使用时弄晕了,就翻书温习下. J ...
- Bootstrap 历练实例-轮播(carousel)插件的事件
事件 下表列出了轮播(Carousel)插件中要用到的事件.这些事件可在函数中当钩子使用. 事件 描述 实例 slide.bs.carousel 当调用 slide 实例方法时立即触发该事件. $(' ...
- 【SQL】连接 —— 内连接、外连接、左连接、右连接、交叉连接
连接 · 内连接 · 外连接 · 左连接 · 右连接 · 全连接 · 交叉连接 · 匹配符号(+) 连接 根据表之间的关系,呈现跨表查询的结果. 外连接 内连接 左连接 右连接 全 ...
- java基础面试题:请说出作用域public,private,protected,以及不写时的区别
不写任何作用域(即访问权限)表示friendly public 公共,权限最大,作用域最大,在类内部.同一package.子孙类.其他package都可以访问 protected保护,在类内部.同一p ...
- 4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍
4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍 天涯明月笙 关注 2018.02.20 19:23* 字数 762 阅读 135 ...
- Datatable 省略显示列中内容,当鼠标放在内容上,悬浮显示全部内容
第一种方法是网上看到的,没成功,贴出来参考一下 <!DOCTYPE html> <html lang="en"> <head> <meta ...
- 三十四、MySQL 函数
MySQL 函数 MySQL 有很多内置的函数,以下列出了这些函数的说明. MySQL 字符串函数 函数 描述 实例 ASCII(s) 返回字符串 s 的第一个字符的 ASCII 码. 返回 Cust ...
- k8s的configMap基本概念及案例
pod中两种特殊类型的存储卷:secret,configMap pod.spec.volumes.secret pod.spec.volumes.configMap多数情况下,这两个存储卷不是给p ...