BZOJ 4826 影魔
本题可以采用主席树的在线做法,只不过常数会 \(super\) 大。
和其他题解差不多,我们先要求出第 \(i\) 个数的 \(l_i\) 和 \(r_i\) ,其中 \(l_i\) 表示左边第一个比它大的点(若没有则为 \(0\) ), \(r_i\) 表示右边比它大的第一个点,若没有则为 \(n+1\) 。
那么对于 \(i\)
点对 \((l_i,r_i)\) 可以有 \(p_1\) 的贡献
点对 \(([l_i+1,i-1],r_i),(l_i,[i+1,r_i-1])\) 可以有 \(p_2\) 的贡献 \((l_i+1<i-1),(i+1<r_i-1)\)
\((i,i+1)\) 也可以有 \(p_1\) 的贡献
有了这么几点,我们就可以拿主席树来维护,对于每个点对,我们以 \(x\) 更新,若 \(x\) 为区间,则以 \(y\) 更新。
用一个单调栈预处理,链表(或 \(vector\) 存储更新信息)。
\(AC \kern 0.4emCODE\):
#include<bits/stdc++.h>
#define ri register int
#define p(i) ++i
#define LL long long
using namespace std;
const int N=2e5+7;
inline int read() {
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
struct node{
int l,r,w;
node(){}
node(int l,int r,int w):l(l),r(r),w(w){}
};
struct E{
int first[N],t;
void init() {t=1;}
struct edge{
int nxt;
node v;
}e[N<<2];
inline void add(int u,node v) {
e[t].v=v;
e[t].nxt=first[u];
first[u]=t++;
}
}E;
struct Seg{
int root[N],tot;
struct Segmenttree{
int l,r;
LL sum,tag;
}T[N*32];
inline void update(int &x,int l,int r,int lt,int rt,int w) {
if (!x) x=p(tot);
T[x].sum+=1ll*(min(r,rt)-max(l,lt)+1)*w;
if (l<=lt&&rt<=r) {T[x].tag+=1ll*w;return;}
int mid=(lt+rt)>>1;
if (l<=mid) update(T[x].l,l,r,lt,mid,w);
if (r>mid) update(T[x].r,l,r,mid+1,rt,w);
}
inline int merge(int x,int y) {
if (!x||!y) return x+y;
T[x].sum+=T[y].sum;T[x].tag+=T[y].tag;
T[x].l=merge(T[x].l,T[y].l);
T[x].r=merge(T[x].r,T[y].r);
return x;
}
inline LL query(int x,int l,int r,int lt,int rt) {
if (!x) return 0;
if (l<=lt&&rt<=r) return T[x].sum;
int mid=(lt+rt)>>1;LL res=0;
if (l<=mid) res+=query(T[x].l,l,r,lt,mid);
if (r>mid) res+=query(T[x].r,l,r,mid+1,rt);
return res+1ll*(min(r,rt)-max(l,lt)+1)*T[x].tag;
}
}T;
int n,st[N],p,pp,at[N],ll[N],rr[N],m;
int main() {
n=read(),m=read(),p=read(),pp=read();
const int p1=p,p2=pp;
int tp=0;
for (ri i(1);i<=n;p(i)) {
at[i]=read();
while(tp&&at[st[tp]]<at[i]) rr[st[tp--]]=i;
ll[i]=st[tp];
st[p(tp)]=i;
}
while(tp) rr[st[tp--]]=n+1;
E.init();
for (ri i(1);i<=n;p(i)) {
if (i!=n) E.add(i,node(i+1,i+1,p1));
if (ll[i]&&rr[i]<=n) E.add(ll[i],node(rr[i],rr[i],p1));
if (ll[i]&&i+1<=rr[i]-1) E.add(ll[i],node(i+1,rr[i]-1,p2));
if (rr[i]<=n&&ll[i]+1<=i-1) E.add(rr[i],node(ll[i]+1,i-1,p2));
}
for (ri i(1);i<=n;p(i)) {
for (ri j(E.first[i]);j;j=E.e[j].nxt) {
node v=E.e[j].v;
int l=v.l,r=v.r,w=v.w;
T.update(T.root[i],l,r,1,n,w);
}
T.root[i]=T.merge(T.root[i],T.root[i-1]);
}
for (ri i(1);i<=m;p(i)) {
int l=read(),r=read();
printf("%lld\n",T.query(T.root[r],l,r,1,n)-T.query(T.root[l-1],l,r,1,n));
}
return 0;
}
BZOJ 4826 影魔的更多相关文章
- 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]影魔
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...
- ●BZOJ 4826 [Hnoi2017]影魔
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4826 题解: 主席树,单调栈 以前还没做过这种维护信息的题,感觉好奇妙. 每对相邻的两个数所 ...
- BZOJ.4826.[AHOI/HNOI2017]影魔(树状数组/莫队 单调栈)
BZOJ LOJ 洛谷 之前看\(mjt\)用莫队写了,以为是一种正解,码了3h结果在LOJ T了没A= = 心态爆炸(upd:发现是用C++11(NOI)交的,用C++11交就快一倍了...) 深刻 ...
- BZOJ 4826 【HNOI2017】 影魔
题目链接:影魔 这道题就是去年序列的弱化版啊…… 我们枚举最大值的位置\(i\),找出左边第一个比\(a_i\)大的位置\(l\),右边第一个比\(a_i\)大的位置\(r\),然后我们分开考虑一下\ ...
- BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树
https://www.lydsy.com/JudgeOnline/problem.php?id=4826 年少不知空间贵,相顾mle空流泪. 和上一道主席树求的东西差不多,求两种对 1. max(a ...
- AC日记——[Hnoi2017]影魔 bzoj 4826
4826 思路: 主席树矩阵加减+单调栈预处理: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 200005 ...
- BZOJ 4826: [Hnoi2017]影魔 单调栈+可持久化线段树
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样 的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个 ...
- BZOJ 4826 [Hnoi2017]影魔 ——扫描线 单调栈
首先用单调栈和扫描线处理出每一个数左面最近的比他大的数在$l[i]$,右面最近的比他大的数$r[i]$. 然后就可以考虑每种贡献是在什么时候产生的. 1.$(l[i],r[i])$产生$p1$的贡献 ...
随机推荐
- 输出数组中出现次数最多且值最大的数字----python
class Solution(): #求最多的数 def find_max(self,list): num = 0 for i in list: print(i) if list.count(i) & ...
- vscode搭建python环境
这两天刚下了一个pycharm,结果使用之后将vscode给崩了,重装的时候有些步骤也记不清,走了一些弯路,做个总结来记录一下(本人觉得vscode比pycharm好用一点). Python下载安装 ...
- 牛客OI测试赛2
题目链接:https://www.nowcoder.com/acm/contest/185#question A.无序组数 暴力求出A和B的因子,注意二元组是无序的,因此还要考虑有些因子在A和B中都存 ...
- 龙芯 loongnix20 rc2 初体验
2021-07-24 v0.0.1 版权声明:原创文章,未经博主允许不得转载 3A5000 昨天发布啦,历史上的昨天是中共一大的第一天. 3A5000 的团购还没开始(大概还是3999左右整机的样子) ...
- centos7 源码安装指定版本的php7
很多时候可能会遇到需要手动源码安装软件的时候,所以自己实践了一把,并且把安装过程中遇到的问题,以及在网上找到的解决办法(实测有效)都记录下来,方便日后学习实践. 1. 系统环境 # cat /etc/ ...
- 简单快速安装Apache+PHP+MySql服务环境(四)—— 将php版本升级到7.2
书接上文,简单快速安装Apache+PHP+MySql服务环境(二)-- centos使用yum安装指定版本的php. 随着各种PHP框架的升级,对PHP的版本也有了更高的要求,所以笔者也尝试着更新升 ...
- Linux 安装 Nodejs 的两种方式
Linux 安装 Nodejs 的两种方式 目录 Linux 安装 Nodejs 的两种方式 一.压缩包安装 Nodejs 二.源码编译安装 Nodejs 一.压缩包安装 Nodejs 下载 Node ...
- java 8新特性 并行流
使用并行流,提高cpu利用率,提高运算速度 /** * java 8并行流 * 底层运用fork join框架 */ @Test public void test(){ Instant start = ...
- U盘启动盘安装win10出现cdboot:couldn't find ntldr
格式化硬盘后出现:cdboot:couldn't find ntldr 解决方法: 分区时格式选择:硬盘格式导致的,一般出现在win10装win7时,需要用pe系统里的分区工具重新给为硬盘分区,并将 ...
- js 日期转为时间戳
在js中,将一个字符转化成Date型也不是什么难事:var str = '2013-08-30'; // 日期字符串str = str.replace(/-/g,'/'); // 将-替换成/,因为下 ...