洛谷P3722 影魔 [AH2017/HNOI2017] 线段树+扫描线
正解:线段树+扫描线
解题报告:
先理解一下这道题,大概是这样儿的:
对于一个点对,如果他们的两端是这段区间的最大值和次大值,那么他们会有p1的贡献
如果他们的两端是最大值和一个非次大值,那么他们会有p2的贡献
问[a,b]内部的点对贡献之和
首先考虑到,两种贡献都要有一个共同点——有最大值
那看到最大值就应该想到单调栈嘛,然后就可以想到,能不能在维护单调栈的时候顺便把答案求出来了 ?
显然是可以的嘛QwQ
那就大力分类讨论一波咯
首先对询问离线,按照右端点排序,然后就直接加入
设现在加入的数是i,对于栈中的第j个元素,有这么几种可能
1)ai>aj
考虑到这是一个单调减的栈,显然这个情况下,点对(i,j)的贡献为p1(它们内部的点对会在后面讨论的不要管QAQ
2)ai<aj
内部又要分类讨论昂
首先如果ai<aj+1
依然是(i,j)的贡献为p1
然后就考虑计算内部的贡献
对于内部的贡献,看到前面的第一种情况,发现对于j之后的单调栈上的点都已经计算过了,贡献为p1,所以就是j点之后的非栈中的点会和i有p2的贡献
那如果ai>aj+1呢
那就从j到其之后的所有点对都会和它有p2的贡献
再仔细思考一下,对于第一种情况,单点修改就好,对于第二种情况的第二小点,区间修改就好
但是对于第二种情况的第一小点,操作起来就很麻烦,还要搞484栈中的点之类的玩意儿,就很麻烦
所以不难想到直接在第一种情况中把贡献改成p1-p2,这样第二种情况中的第一小点就能直接做了,全部加上就好
然后就做完辣!
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define rg register
#define gc getchar()
#define ll long long
#define ls(x) (x<<1)
#define rs(x) ((x<<1)|1)
#define rp(i,x,y) for(rg ll i=x;i<=y;++i) const ll N=+;
ll n,m,a[N],top,stck[N],p1,p2,as[N];
struct node{ll l,r,id;}ques[N]; il ll read()
{
rg char ch=gc;rg ll x=;rg bool y=;
while(ch!='-' && (ch>'' || ch<''))ch=gc;
if(ch=='-')ch=gc,y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=gc;
return y?x:-x;
}
struct tree
{
ll tr[N<<],ad[N<<];
il void pushdown(ll x,ll l,ll r,ll mid){if(ad[x])tr[ls(x)]+=(ll)(mid-l+)*ad[x],ad[ls(x)]+=ad[x];tr[rs(x)]+=(r-mid)*ad[x],ad[rs(x)]+=ad[x],ad[x]=;}
il void pushup(ll x){tr[x]=tr[ls(x)]+tr[rs(x)];}
void modify(ll x,ll l,ll r,ll to_l,ll to_r,ll dat)
{
if(to_l<=l && r<=to_r){tr[x]+=(ll)dat*(r-l+);ad[x]+=dat;return;}
ll mid=(l+r)>>;pushdown(x,l,r,mid);
if(mid>=to_l)modify(ls(x),l,mid,to_l,to_r,dat);if(mid<to_r)modify(rs(x),mid+,r,to_l,to_r,dat);pushup(x);
}
ll query(ll x,ll l,ll r,ll to_l,ll to_r)
{
if(to_l<=l && r<=to_r)return tr[x];
ll mid=(l+r)>>,ret=;pushdown(x,l,r,mid);
if(mid>=to_l)ret+=query(ls(x),l,mid,to_l,to_r);
if(mid<to_r)ret+=query(rs(x),mid+,r,to_l,to_r);
return ret;
}
il void clr(ll x,ll l,ll r,ll to)
{
if(l==r)return void(tr[x]=ad[x]=);
ll mid=(l+r)>>;pushdown(x,l,r,mid);if(mid>=to)clr(ls(x),l,mid,to);else clr(rs(x),mid+,r,to);pushup(x);
}
}instck,notin;
il bool cmp(node gd,node gs){return gd.r<gs.r;} int main()
{
freopen("ym.in","r",stdin);freopen("ym.out","w",stdout);
n=read();m=read();p1=read();p2=read();rp(i,,n)a[i]=read();rp(i,,m)ques[i].l=read(),ques[i].r=read(),ques[i].id=i;sort(ques+,ques++m,cmp);
rp(i,,m)
{
while(ques[i-].r<ques[i].r)
{
++ques[i-].r;
while(top && a[ques[i-].r]>a[stck[top]])notin.modify(,,n,stck[top],stck[top],instck.query(,,n,top,top)+p1-p2),instck.clr(,,n,top--);
if(top)instck.modify(,,n,top,top,p1-p2),instck.modify(,,n,,top,p2);
if(stck[top]+<=ques[i-].r)notin.modify(,,n,stck[top]+,ques[i-].r-,p2);stck[++top]=ques[i-].r;
}
as[ques[i].id]=notin.query(,,n,ques[i].l,ques[i].r)+instck.query(,,n,lower_bound(stck+,stck+top+,ques[i].l)-stck,top);
}
rp(i,,m)printf("%lld\n",as[i]);
return ;
}
//看起来并不多的样子,,,其实打死我了TT
然后我一边觉得这题好实现一边花式打错魔改了3h,,,心态崩了TT真实想死了TT
洛谷P3722 影魔 [AH2017/HNOI2017] 线段树+扫描线的更多相关文章
- 洛谷 P3373 【模板】线段树 2
洛谷 P3373 [模板]线段树 2 洛谷传送门 题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一 ...
- 洛谷P3372 【模板】线段树 1
P3372 [模板]线段树 1 153通过 525提交 题目提供者HansBug 标签 难度普及+/提高 提交 讨论 题解 最新讨论 [模板]线段树1(AAAAAAAAA- [模板]线段树1 洛谷 ...
- 洛谷P4891 序列(势能线段树)
洛谷题目传送门 闲话 考场上一眼看出这是个毒瘤线段树准备杠题,发现实在太难调了,被各路神犇虐哭qwq 考后看到各种优雅的暴力AC......宝宝心里苦qwq 思路分析 题面里面是一堆乱七八糟的限制和性 ...
- 洛谷 P2574 XOR的艺术(线段树 区间异或 区间求和)
To 洛谷.2574 XOR的艺术 题目描述 AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏.在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下 1. 拥有一个伤害串为长度为n的 ...
- 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块
!!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...
- Bzoj5294/洛谷P4428 [Bjoi2018]二进制(线段树)
题面 Bzoj 洛谷 题解 考虑一个什么样的区间满足重组之后可以变成\(3\)的倍数.不妨设\(tot\)为一个区间内\(1\)的个数.如果\(tot\)是个偶数,则这个区间一定是\(3\)的倍数,接 ...
- 【题解】洛谷P1198 [JSOI2008] 最大数(线段树)
洛谷P1198:https://www.luogu.org/problemnew/show/P1198 思路 一道水水的线段树 20分钟A掉 这道题只涉及到单点修改和区间查询 所以这道题甚至不用Laz ...
- bzoj3064/洛谷P4314 CPU监控【线段树】
好,长草博客被催更了[?] 我感觉这题完全可以当作线段树3 线段树2考加法和乘法标记的下放顺序,这道题更丧心病狂[?] 很多人可能跟我一样,刚看到这道题秒出思路:打一个当前最大值一个历史最大值不就完事 ...
- 洛谷P3373 【模板】线段树 2
P3373 [模板]线段树 2 47通过 186提交 题目提供者HansBug 标签 难度提高+/省选- 提交 讨论 题解 最新讨论 为啥WA(TAT) 题目描述 如题,已知一个数列,你需要进行 ...
随机推荐
- Android——RecycleView
RecycleView设置点击事件 http://blog.csdn.net/guxiao1201/article/details/40423361
- SOLID原则 【转】
S.O.L.I.D 是面向对象设计(OOD)和面向对象编程(OOP)中的几个重要编码原则(Programming Priciple)的首字母缩写. 面向对象设计的原则 SRP The Single ...
- 教你一招:使用最快速的方式激活windows10专业版
1.安装win10专业版 2.在桌面新建“文本文档.txt” 3.复制如下代码到新新建的“文本文档.txt”中 slmgr /ipk VK7JG-NPHTM-C97JM-9MPGT-3V66T slm ...
- 3D 特征点概述(2)
还是紧接着上一文章的思路继续介绍3D特征点的基本概念问题,还是这个表格: Feature Name Supports Texture / Color Local / Global / Regional ...
- Java知多少(10)数据类型及变量
Java 是一种“强类型”的语言,声明变量时必须指明数据类型.变量(variable)占据一定的内存空间.不同类型的变量占据不同的大小. Java中共有8种基本数据类型,包括4 种整型.2 种浮点型. ...
- R语言系列:生成数据
R语言系列:生成数据 (2014-05-04 17:41:57) 转载▼ 标签: r语言 教育 分类: 生物信息 生成规则数据1.使用“:“,如x=1:10,注意该方法既可以递增也可以递减,如y=10 ...
- 注解实现Bean依赖注入
12.2.1 概述 注解实现Bean配置主要用来进行如依赖注入.生命周期回调方法定义等,不能消除XML文件中的Bean元数据定义,且基于XML配置中的依赖注入的数据将覆盖基于注解配置中的依赖注入的数 ...
- python实现微信接口——itchat模块
python实现微信接口——itchat模块 安装 sudo pip install itchat 登录 itchat.auto_login() 这种方法将会通过微信扫描二维码登录,但是这种登录的方 ...
- iOS - UIAlertController三种显示提示框代码
UIAlertView在IOS 8以上版本已经过时了,官方推荐我们使用UIAlertController代替UIAlertView.UIActionSheet 1、UIAlertController显 ...
- struts2常用标签详解(申明:来源于网络)
struts2常用标签详解(申明:来源于网络) 地址:http://blessht.iteye.com/blog/1184960