[BZOJ4826][HNOI2017]影魔 可持久化线段树
题意:给你 \(1\) 到 \(n\) 的排列 \(k_1,k_2,\dots,k_n\) ,对 \(i,j (i<j)\)来说,若不存在 \(k_s (i<s<j)\) 大于 \(k_i\) 或者 \(k_j\),则会产生 \(p_1\) 的贡献。另一种情况,令 \(c\) 为 \(k_{i + 1}, k_{i + 2}, \cdots, k_{j -1}\) 的最大值,若 \(c\) 满足:\(k_i < c < k_j\),或者 \(k_j < c < k_i\),则会为产生 \(p_2\) 的贡献 ,多次询问区间 \([l_i,r_i]\) 的贡献值
题解
第一种情况,\(k_i\) 和 \(k_j\) 是 \([i,j]\) 的最大值和次大值,第二种情况,是最大值和第三大值
对于每个 \(i\) ,用单调栈预处理出它左边第一个比他大的位置 \(lpos[i]\) ,右边第一个比他大的位置 \(rpos[i]\) ,那么第一种情况是所有的 \(lpos[i],rpos[i]\) 和 \(i,i+1\) (前者并不会算重复),第二种情况是所有的 \(lpos[i],i+1\dots rpos[i]-1\) 和 \(lpos[i]+1\dots i-1,rpos[i]\)
由于是询问区间 \([l,r]\) 的值,而且发现上述所有的点对,某一点都是定的,因此开一棵可持久化线段树搞一下这个(相当于查询二维坐标系下 \((l,l)\) 到 \((r,r)\) 这个矩形区域的值)
好像有扫描线的做法,不过我不会扫描线,先留个坑以后再补(咕咕咕)
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
const int S=1<<18;
char ibuf[S],*iS,*iT;
#define gc (iS==iT?iT=ibuf+fread(iS=ibuf,1,S,stdin),iS==iT?EOF:*iS++:*iS++)
inline int read(){char c,p=0;int w;
while(isspace(c=gc));if(c=='-')p=1,c=gc;w=c&15;
while(isdigit(c=gc))w=w*10+(c&15);return p?-w:w;
}
template<typename T,typename U>inline bool smin(T&x,const U&y){return x>y?x=y,1:0;}
template<typename T,typename U>inline bool smax(T&x,const U&y){return x<y?x=y,1:0;}
typedef long long ll;
const int N=2e5+5;
struct node{
int ls,rs,w;ll sum;
}t[N*70];
int n,m,p1,p2,cnt,rt[N],a[N],s[N],top,lpos[N],rpos[N];
inline void ins(int&o,int l,int r,int x,int y,int z){
t[++cnt]=t[o];t[o=cnt].sum+=1ll*(y-x+1)*z;
if(x<=l&&r<=y){t[o].w+=z;return;}
int mid=l+r>>1;
if(y<=mid)ins(t[o].ls,l,mid,x,y,z);
else if(x>mid)ins(t[o].rs,mid+1,r,x,y,z);
else ins(t[o].ls,l,mid,x,mid,z),ins(t[o].rs,mid+1,r,mid+1,y,z);
}
inline ll ask(int x,int y,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return t[y].sum-t[x].sum;
int mid=l+r>>1;ll ans=1ll*(qr-ql+1)*(t[y].w-t[x].w);
if(qr<=mid)return ans+ask(t[x].ls,t[y].ls,l,mid,ql,qr);
if(ql>mid)return ans+ask(t[x].rs,t[y].rs,mid+1,r,ql,qr);
return ans+ask(t[x].ls,t[y].ls,l,mid,ql,mid)+ask(t[x].rs,t[y].rs,mid+1,r,mid+1,qr);
}
struct data{int l,r,w;};
std::vector<data>g[N];
#define pb push_back
int main(){
n=read(),m=read(),p1=read(),p2=read();
REP(i,1,n)a[i]=read();
s[top=1]=0;a[0]=a[n+1]=1e9;
REP(i,1,n){
while(top&&a[i]>a[s[top]])--top;
lpos[i]=s[top];s[++top]=i;
}
s[top=1]=n+1;
for(int i=n;i;--i){
while(top&&a[i]>a[s[top]])--top;
rpos[i]=s[top];s[++top]=i;
}
REP(i,1,n){
if(i<n)g[i].pb((data){i+1,i+1,p1});
if(lpos[i]&&rpos[i]<=n)g[lpos[i]].pb((data){rpos[i],rpos[i],p1});
if(lpos[i]&&i<rpos[i]-1)g[lpos[i]].pb((data){i+1,rpos[i]-1,p2});
if(rpos[i]<=n&&i>lpos[i]+1)g[rpos[i]].pb((data){lpos[i]+1,i-1,p2});
}
REP(i,1,n){
rt[i]=rt[i-1];
const int sz=g[i].size();
for(int j=0;j<sz;++j)ins(rt[i],1,n,g[i][j].l,g[i][j].r,g[i][j].w);
}
while(m--){
int x=read(),y=read();
printf("%lld\n",ask(rt[x-1],rt[y],1,n,x,y));
}
return 0;
}
[BZOJ4826][HNOI2017]影魔 可持久化线段树的更多相关文章
- [BZOJ4826] [HNOI2017] 影魔 单调栈 主席树
题面 因为是一个排列,所以不会有重复的.如果有重复就没法做了.一开始没有仔细看题目想了半天. 发现,如果是第一种情况,那么边界\(l\)和\(r\)就应该分别是整个区间的最大值和次大值. 然后,对于那 ...
- 【bzoj4826】[Hnoi2017]影魔 单调栈+可持久化线段树
题目描述 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...
- bzoj千题计划196:bzoj4826: [Hnoi2017]影魔
http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...
- 【bzoj3956】Count 单调栈+可持久化线段树
题目描述 输入 输出 样例输入 3 2 0 2 1 2 1 1 1 3 样例输出 0 3 题解 单调栈+可持久化线段树 本题是 bzoj4826 的弱化版(我为什么做题总喜欢先挑难的做QAQ) $k$ ...
- PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树
#44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- 【BZOJ-2653】middle 可持久化线段树 + 二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1298 Solved: 734[Submit][Status][Discu ...
- HDU 4866 Shooting(持久化线段树)
view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...
- 【BZOJ-3653】谈笑风生 DFS序 + 可持久化线段树
3653: 谈笑风生 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 628 Solved: 245[Submit][Status][Discuss] ...
随机推荐
- NOIp2018模拟赛四十一
现在是下午15:36,我已经改完题了...刷新纪录 A题叫B,B题叫A是什么操作??? 我离200只差一个SBFA.jpg 成绩:0+100+10=110 被虐啦...今天九个阿克的Orz.A题是个神 ...
- 【BZOJ4444】国旗计划 - 决策单调性
Description A国正在开展一项伟大的计划——国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了N名优秀的边 ...
- ES 新增字符串方法
话不多说,直接开鲁 1. startsWith() 作用: 检测字符串以什么开头 实例: let str = "www.qjzzj.top"; console.log(str.st ...
- Markdown语法简记
目录 一.标题 1. 六个级别的标题 2. 主.副两级标题 二.根据标题生成文档结构大纲 三.字体 1. 斜体 2. 粗体 3. 倾斜加粗 4. 行首缩进 5. 删除线 四.引用块 五.代码块 1. ...
- 处理Oracle 11g在用EXP导出时,空表不能导出
一.问题原因: 11G中有个新特性,当表无数据时,不分配segment,以节省空间 想要给空表也分配segmant,有以下两个办法: 1.insert一行,再rollback就产生segmen ...
- hdoj-5099-Comparison of Android versions
Comparison of Android versions Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- uva_127,栈以及vector的应用
参考自http://www.cnblogs.com/maqiang/archive/2012/05/02/2479760.html #include <iostream> #include ...
- MDNS DDoS 反射放大攻击——攻击者假冒被攻击者IP向网络发送DNS请求,域名为“_services._dns-sd._udp.local”,这将引起本地网络中所有提供服务的主机都向被攻击者IP发送DNS响应,列举网络中所有服务
MDNS Reflection DDoS 2015年3月,有报告叙述了mDNS 成为反射式和放大式 DDoS 攻击中所用媒介的可能性,并详述了 mDNS 反射式攻击的原理和相应防御方式.Q3,Akam ...
- Android--ViewPager-Fragment
package com.cnn.viewpager02; import java.util.ArrayList; import java.util.List; import android.os.Bu ...
- 基于opencv的手写数字字符识别
摘要 本程序主要参照论文,<基于OpenCV的脱机手写字符识别技术>实现了,对于手写阿拉伯数字的识别工作.识别工作分为三大步骤:预处理,特征提取,分类识别.预处理过程主要找到图像的ROI部 ...