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)加入一个点,删 ...
随机推荐
- css img 等比例自动缩放
按父容器宽度自动缩放,并且保持图片原本的长宽比 img{ width: auto; height: auto; max-width: 100%; max-height: 100%; }
- python_43_移动文件指针补充
#移动文件指针补充 ''' 文件对象.seek((offset,where)) offset:移动的偏移量,单位为字节.等于正数时向文件尾方向移动,等于负数时向文件头方向移动文件指针 where:指针 ...
- CentOS6.5下载地址
http://linux.xitongxz.net:808/201603/CentOS-6.5-x86_64-bin-DVD1.iso
- OO第13-14次作业总结
目录 面向对象第13-14次作业总结博客 1.设计分析 2.架构总结.测试 3.课程收获和建议 面向对象第13-14次作业总结博客 1.设计分析 这个单元是我做的最差的一个单元.总工程量超过2000行 ...
- java设计模式——单例模式(二)
破坏单例模式 上一章节,介绍了单例模式的几种方式,这次来学习一波我们创建的单例模式是否安全,能不能破坏.换句话说,也就是在程序运行中,不止有一个实例. 一. 序列化,反序列化破坏 以饿汉式的单例模式 ...
- java设计模式——抽象工程模式
一. 定义与类型 定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类 类型:创建型 二. 适用场景 客户端不依赖于产品类实例如何备创建,实现等细节 创建一系列相关的产品 ...
- 人品计算器 JFrame 窗体软件版 JPanel JTextField JTextArea JButtton JLabel setContentPane Swing包(用户界面工具包)
import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; import java.awt.eve ...
- java面向对象思想2
1.主函数是一类特殊的函数,作为程序入口,可被虚拟机调用.主函数格式是固定的.public:函数访问权限最大.static:代表函数随着类的加载已经存在.void:主函数没有具体返回值.main:不是 ...
- [BZOJ] 3875: [Ahoi2014&Jsoi2014]骑士游戏
设\(f[x]\)为彻底杀死\(x\)号怪兽的代价 有转移方程 \[ f[x]=min\{k[x],s[x]+\sum f[v]\} \] 其中\(v\)是\(x\)通过普通攻击分裂出的小怪兽 这个东 ...
- 简单的Maven+SpringMVC
一.SpringMVC非注解编程 1:修改pom.xml文件(相当于非Maven项目的导入jar包) <!-- https://mvnrepository.com/artifact/org.sp ...