刷题总结——影魔(HNOI2017 BZOJ4826 线段树+扫描线)
题目:
Description
Input
Output
Sample Input
7 9 5 1 3 10 6 8 2 4
1 7
1 9
1 3
5 9
1 5
Sample Output
39
4
13
16
HINT
Source
题解:
引用下lcf2000的题解,%%%%%%%%
我们枚举最大值的位置i,找出左边第一个比ai大的位置l,右边第一个比ai大的位置r,然后我们分开考虑一下p1和p2的贡献。
首先由于ai为最大值,那么左端点不会小于l,右端点不会大于r。
容易发现只有左端点为l,右端点为r才会产生p1的贡献然后产生p2贡献的有两种:一种是左端点为l,右端点在区间(i,r)中;另一种是左端点区间(l,i)中,右端点为r。
还有一种情况需要考虑,就是左端点和右端点差为1,会产生p1的贡献。对每个询问直接计算就可以了。
所以这个问题可以抽象到二维平面上。有一些点和一些线段都有权值,每次询问某个矩形内部的权值和。
于是离线排序+扫描线+树状数组即可。
自己再说一两句吧···
这道题最先开始要想到的是每次考虑对答案贡献的时候首先要想到的是枚举中间的点···而不是两旁·····
其实这种考虑贡献对象的思路在很多地方都有用到···比如有时做与树有关的题很多时候我们考虑对答案贡献都是考虑每一条边·····希望下次遇到这种题能记住这种思想···
然后就是转二维平面····这个其实比较好想···毕竟看到了点对嘛···
想到转二维那么扫描线和线段树(我是用线段树写的··对带区间修改的树状数组不是太熟···)就是顺理成章的的事情了···
然而转二维时有个细节要注意····一个点可能没有左边第一个比自己大的位置l,或者没有右边第一个比自己大的位置r,如果仅仅是这二者中间少了一个···它也是会对答案产生贡献的···比如7 9 10中的9·····md因为这一点被样例卡着过不去23333
然后就是排序了···修改一定要排在询问前面当高度相同时··这点在cdq分治时其实经常提到·····一定要注意了
最后吐槽一句洛谷为毛要卡线段树啊艹···现在哪有放树状数组不放线段树的···还是bzoj不坑···
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
using namespace std;
const int N=2e5+;
struct node
{
int x,y,h,v,id;
}q[N*];
int n,m,p1,p2,stack[N],top,num[N],Le[N],Ri[N],cnt,tag[N*];
long long ans[N],tree[N*];
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f;
}
inline bool cmp(node a,node b)
{
if(a.h==b.h) return a.id<b.id;
return a.h<b.h;
}
inline void add(int k,int l,int r,int v)
{
tree[k]+=(long long)(r-l+)*v;
tag[k]+=v;
}
inline void pushdown(int k,int l,int r,int mid)
{
if(tag[k])
{
add(k*,l,mid,tag[k]);
add(k*+,mid+,r,tag[k]);
tag[k]=;
}
}
inline void modify(int k,int l,int r,int x,int y,int v)
{
if(l>=x&&r<=y)
{
add(k,l,r,v);
return;
}
int mid=(l+r)/;
pushdown(k,l,r,mid);
if(x<=mid) modify(k*,l,mid,x,y,v);
if(y>mid) modify(k*+,mid+,r,x,y,v);
tree[k]=tree[k*]+tree[k*+];
}
inline long long query(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
return tree[k];
int mid=(l+r)/;
pushdown(k,l,r,mid);long long temp=;
if(x<=mid) temp+=query(k*,l,mid,x,y);
if(y>mid) temp+=query(k*+,mid+,r,x,y);
return temp;
}
int main()
{
//freopen("a.in","r",stdin);
n=R(),m=R(),p1=R(),p2=R();int a,b;
for(int i=;i<=n;i++) num[i]=R();
for(int i=;i<=n;i++)
{
while(top&&num[i]>num[stack[top]]) Ri[stack[top]]=i,top--;
if(top) Le[i]=stack[top];
stack[++top]=i;
}
for(int i=;i<=m;i++)
{
a=R(),b=R();ans[i]=(long long)(b-a)*p1;
q[++cnt].x=a,q[cnt].y=b,q[cnt].h=a-,q[cnt].v=-;q[cnt].id=i;
q[++cnt].x=a,q[cnt].y=b,q[cnt].h=b,q[cnt].v=;q[cnt].id=i;
}
for(int i=;i<=n;i++)
{
if(Ri[i]&&Le[i])
{
q[++cnt].x=Le[i],q[cnt].y=Le[i],q[cnt].h=Ri[i],q[cnt].v=p1;
if(Le[i]<i-) q[++cnt].x=Le[i]+,q[cnt].y=i-,q[cnt].h=Ri[i],q[cnt].v=p2;
if(Ri[i]>i+) q[++cnt].x=i+,q[cnt].y=Ri[i]-,q[cnt].h=Le[i],q[cnt].v=p2;
}
else if(Ri[i])
{
if(i>) q[++cnt].x=,q[cnt].y=i-,q[cnt].h=Ri[i],q[cnt].v=p2;
}
else if(Le[i])
{
if(i<n) q[++cnt].x=i+,q[cnt].y=n,q[cnt].h=Le[i],q[cnt].v=p2;
}
}
sort(q+,q+cnt+,cmp);
for(int i=;i<=cnt;i++)
{
if(q[i].id)
ans[q[i].id]+=(long long)q[i].v*query(,,n,q[i].x,q[i].y);
else
modify(,,n,q[i].x,q[i].y,q[i].v);
}
for(int i=;i<=m;i++)
printf("%lld\n",ans[i]);
return ;
}
刷题总结——影魔(HNOI2017 BZOJ4826 线段树+扫描线)的更多相关文章
- 刷题总结——旅馆(bzoj1593线段树)
题目: Description 奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光.作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿.这个巨大的旅馆一共有N ( ...
- 洛谷P3722 影魔 [AH2017/HNOI2017] 线段树+扫描线
正解:线段树+扫描线 解题报告: 传送门! 先理解一下这道题,大概是这样儿的: 对于一个点对,如果他们的两端是这段区间的最大值和次大值,那么他们会有p1的贡献 如果他们的两端是最大值和一个非次大值,那 ...
- 洛谷P3246 序列 [HNOI2016] 莫队/线段树+扫描线
正解:莫队/线段树+扫描线 解题报告: 传送门! 似乎是有两种方法的,,,所以分别港下好了QAQ 第一种,莫队 看到这种询问很多区间之类的就会自然而然地想到莫队趴?然后仔细思考一下,发现复杂度似乎是欧 ...
- 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)
D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...
- 【POJ-2482】Stars in your window 线段树 + 扫描线
Stars in Your Window Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11706 Accepted: ...
- BZOJ-3225 立方体覆盖 线段树+扫描线+乱搞
看数据范围像是个暴力,而且理论复杂度似乎可行,然后被卡了两个点...然后来了个乱搞的线段树+扫描线.. 3225: [Sdoi2008]立方体覆盖 Time Limit: 2 Sec Memory L ...
- hdu 5091(线段树+扫描线)
上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...
- POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...
- 2018牛客网暑假ACM多校训练赛(第四场)E Skyline 线段树 扫描线
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round4-E.html 题目传送门 - https://www.no ...
随机推荐
- code Gym 100500D T-shirts(暴力)
因为只能买一次,暴力枚举一下买的衣服的大小. #include<cstdio> #include<map> #include<algorithm> using na ...
- [视觉] 基于YoloV3的实时摄像头记牌器
基于YoloV3的实时摄像头记牌器 github:https://github.com/aoru45/cards_recognition_recorder_pytorch 最终效果 数据准备 数据获取 ...
- Fruit Ninja(取随机数)
链接:https://www.nowcoder.com/acm/contest/163/A来源:牛客网 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C++ 262144K,其他语言524 ...
- stixel-world跑在kitti数据集
kitti数据集中每一帧的Calibration不同,每一帧都存储了4个相机的Calibration http://ww.cvlibs.net/publications/Geiger2013IJRR. ...
- python_88_xml模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单例如创建xmltest.xml文件内容如上 注:/代表自结束符号 <?xml version=&quo ...
- python之*的魔性用法
1. *在函数中的作用 聚合 在函数定义时聚合 def eat(args): print('我请你吃:',args) eat('蒸羊羔儿') # 输出结果 # 我请你吃: 蒸羊羔儿 打散 在函数执行时 ...
- Idea01 Idea2018中集成Tomcat9导致OutPut乱码
版本和平台 idea2018.3 tomcat9 jdk1.8 windows7 64位 output乱码 经过测试,项目编码格式设置为utf-8,在main方法中输出中文正常. 而iedea集成to ...
- 阿里云服务器下安装LAMP环境(CentOS Linux 6.3)
http://ninghao.net/course/514 http://www.sphinxsearch.org/archives/243 ctrl + l putty 清理屏幕 apache 自 ...
- 01_13_Struts_默认Action
01_13_Struts_默认Action 1. 配置struts默认Action <package name="default" namespace="/&quo ...
- 使用lua做序列化和反序列化
-- lua对象序列化 function serialize(obj) local lua = "" local t = type(obj) if t == "numbe ...