[AH/HNOI2017]影魔
题目背景
影魔,奈文摩尔,据说有着一个诗人的灵魂。 事实上,他吞噬的诗人灵魂早已成千上万。
千百年来,他收集了各式各样的灵魂,包括诗人、 牧师、 帝王、 乞丐、 奴隶、 罪人,当然,还有英雄。
题目描述
每一个灵魂,都有着自己的战斗力,而影魔,靠这些战斗力提升自己的攻击。
奈文摩尔有 n 个灵魂,他们在影魔宽广的体内可以排成一排,从左至右标号 1 到 n。第 i个灵魂的战斗力为 k[i],灵魂们以点对的形式为影魔提供攻击力,对于灵魂对 i, j(i<j)来说,若不存在 ks大 于 k[i]或者 k[j],则会为影魔提供 p1 的攻击力(可理解为: 当 j=i+1 时,因为不存在满足 i<s<j 的 s,从而 k[s]不存在,这时提供 p1 的攻击力;当 j>i+1 时,若max{k[s]|i<s<j}<=min{k[i],k[j]} , 则 提 供 p1 的 攻 击 力 ); 另 一 种 情 况 , 令 c 为k[i+1],k[i+2],k[i+3]……k[j-1]的最大值,若 c 满足: k[i]<c<k[j],或者 k[j]<c<k[i],则会为影魔提供 p2 的攻击力,当这样的 c 不存在时,自然不会提供这 p2 的攻击力;其他情况的点对,均不会为影魔提供攻击力。
影魔的挚友噬魂鬼在一天造访影魔体内时被这些灵魂吸引住了,他想知道,对于任意一段区间[a,b], 1<=a<b<=n,位于这些区间中的灵魂对会为影魔提供多少攻击力,即考虑 所有满足a<=i<j<=b 的灵魂对 i,j 提供的攻击力之和。
顺带一提,灵魂的战斗力组成一个 1 到 n 的排列: k[1],k[2],…,k[n]。
输入输出格式
输入格式:
输入文件名为 sf.in。
第一行 n,m,p1,p2
第二行 n 个数: k[1],k[2],…,k[n]
接下来 m 行, 每行两个数 a,b, 表示询问区间[a,b]中的灵魂对会为影魔提供多少攻击力。
输出格式:
输出文件名为 sf.out
共输出 m 行,每行一个答案,依次对应 m 个询问。
输入输出样例
10 5 2 3
7 9 5 1 3 10 6 8 2 4
1 7
1 9
1 3
5 9
1 5
30
39
4
13
16
说明
30%: 1<= n,m <= 500。
另 30%: p1=2*p2。
100%:1 <= n,m <= 200000; 1 <= p1,p2 <= 1000。
补上一个更好理解的方法:主席树
令L[i]为i前第一个比a[i]大的一位,R[i]为i后第一个比a[i]大的一位
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long lol;
struct ZYYS
{
int c,p,l,r;
}q[];
int pos,ch[][],root[],a[],sta[],top,n,m,lst[],nxt[],cnt;
lol sum[],lazy[],p1,p2;
bool cmp(ZYYS a,ZYYS b)
{
return a.p<b.p;
}
void update(int &rt,int l,int r,int L,int R,lol k,int last)
{
int x=rt;
if (rt<=last)
{
rt=++pos;
ch[rt][]=ch[x][];ch[rt][]=ch[x][];
sum[rt]=sum[x];
lazy[rt]=lazy[x];
}
if (l>=L&&r<=R)
{
sum[rt]+=(r-l+)*k;
lazy[rt]+=k;
return ;
}
int mid=(l+r)/;
if (L<=mid) update(ch[rt][],l,mid,L,R,k,last);
if (R>mid) update(ch[rt][],mid+,r,L,R,k,last);
sum[rt]=sum[ch[rt][]]+sum[ch[rt][]]+(r-l+)*lazy[rt];
}
lol query(int x,int y,int l,int r,int L,int R,lol la)
{
if (l>=L&&r<=R)
{
return sum[y]-sum[x]+la*(r-l+);
}
int mid=(l+r)/;
lol s=;
if (L<=mid) s+=query(ch[x][],ch[y][],l,mid,L,R,la+lazy[y]-lazy[x]);
if (R>mid) s+=query(ch[x][],ch[y][],mid+,r,L,R,la+lazy[y]-lazy[x]);
return s;
}
int main()
{int i,x,l,r,last=;
cin>>n>>m>>p1>>p2;
for (i=;i<=n;i++)
scanf("%d",&a[i]);
top=;
for (i=;i<=n;i++)
{
while (top&&a[sta[top]]<a[i]) top--;
lst[i]=sta[top];
top++;
sta[top]=i;
}
top=;
sta[]=n+;
for (i=n;i>=;i--)
{
while (top&&a[sta[top]]<a[i]) top--;
nxt[i]=sta[top];
top++;
sta[top]=i;
}
for (i=;i<=n;i++)
{
if (lst[i]&&nxt[i]<=n)
{
q[++cnt]=(ZYYS){,lst[i],nxt[i],nxt[i]};
q[++cnt]=(ZYYS){,nxt[i],lst[i],lst[i]};
}
if (lst[i]&&nxt[i]-i>)
q[++cnt]=(ZYYS){,lst[i],i+,nxt[i]-};
if (nxt[i]<=n&&i-lst[i]>)
q[++cnt]=(ZYYS){,nxt[i],lst[i]+,i-};
}
sort(q+,q+cnt+,cmp);
x=;
last=;
for (i=;i<=cnt;i++)
{
while (x<q[i].p) root[x+]=root[x],x++,last=pos;
if (q[i].c==)
update(root[x],,n,q[i].l,q[i].r,p1,last);
else update(root[x],,n,q[i].l,q[i].r,*p2,last);
}
while (x<n) root[x+]=root[x],x++;
for (i=;i<=m;i++)
{
scanf("%d%d",&l,&r);
printf("%lld\n",query(root[l-],root[r],,n,l,r,)/+(r-l)*p1);
}
}
线段树:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Ask
{
int l,r,id;
}q[];
int a[],aa[],n,m,stack[],R[];
long long c[],mark[],ans[],p1,p2;
bool cmp(Ask a,Ask b)
{
return a.l<b.l;
}
void pushup(int rt)
{
c[rt]=c[rt*]+c[rt*+];
}
void pushdown(int rt,int l,int r,int mid)
{
if (mark[rt])
{
mark[rt*]+=mark[rt];
mark[rt*+]+=mark[rt];
c[rt*]+=mark[rt]*(mid-l+);
c[rt*+]+=mark[rt]*(r-mid);
mark[rt]=;
}
}
void change(int rt,int l,int r,int L,int R,long long d)
{
if (l>=L&&r<=R)
{
mark[rt]+=d;
c[rt]+=(r-l+)*d;
return;
}
pushdown(rt,l,r,(l+r)/);
int mid=(l+r)/;
if (L<=mid) change(rt*,l,mid,L,R,d);
if (R>mid) change(rt*+,mid+,r,L,R,d);
pushup(rt);
}
long long getsum(int rt,int l,int r,int L,int R)
{
if (l>=L&&r<=R)
{
return c[rt];
}
int mid=(l+r)/;
pushdown(rt,l,r,mid);
long long s=;
if (L<=mid) s+=getsum(rt*,l,mid,L,R);
if (R>mid) s+=getsum(rt*+,mid+,r,L,R);
pushup(rt);
return s;
}
void work()
{int i;
memset(c,,sizeof(c));
memset(mark,,sizeof(mark));
sort(q+,q+m+,cmp);
int top=;
stack[]=n+;
for (i=n;i>=;i--)
{
while (top&&a[i]>=a[stack[top]]) top--;
R[i]=stack[top];
stack[++top]=i;
}
top=m;
for (i=n;i>=;i--)
{
if (i+<=R[i]-)
change(,,n,i+,R[i]-,p2);
change(,,n,R[i],R[i],p1-p2);
while (top&&q[top].l==i)
ans[q[top].id]+=getsum(,,n,,q[top].r),top--;
}
}
void rev()
{int i;
for (i=;i<=n;i++)
aa[i]=a[n-i+];
for (i=;i<=n;i++)
a[i]=aa[i];
}
int main()
{int i;
cin>>n>>m>>p1>>p2;
for (i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
for (i=;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
work();
rev();
for (i=;i<=m;i++)
q[i].l=n+-q[i].l,q[i].r=n+-q[i].r,swap(q[i].l,q[i].r);
work();
for (i=;i<=m;i++)
printf("%lld\n",ans[i]);
}
庆祝FGO第一/二个SSR
[AH/HNOI2017]影魔的更多相关文章
- bzoj 4826: [Hnoi2017]影魔 [主席树 单调栈]
4826: [Hnoi2017]影魔 题意:一个排列,点对\((i,j)\),\(p=max(i+1,j-1)\),若\(p<a_i,a_j\)贡献p1,若\(p\)在\(a_1,a_2\)之间 ...
- 4826: [Hnoi2017]影魔
4826: [Hnoi2017]影魔 https://lydsy.com/JudgeOnline/problem.php?id=4826 分析: 莫队+单调栈+st表. 考虑如何O(1)加入一个点,删 ...
- 【LG3722】[HNOI2017]影魔
[LG3722][HNOI2017]影魔 题面 洛谷 题解 先使用单调栈求出\(i\)左边第一个比\(i\)大的位置\(lp_i\),和右边第一个比\(i\)大的位置\(rp_i\). 考虑\(i\) ...
- [BZOJ4826][HNOI2017]影魔(主席树)
4826: [Hnoi2017]影魔 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 669 Solved: 384[Submit][Status][ ...
- 【BZOJ4826】[Hnoi2017]影魔 单调栈+扫描线
[BZOJ4826][Hnoi2017]影魔 Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝 ...
- [bzoj4826][Hnoi2017]影魔_单调栈_主席树
影魔 bzoj-4826 Hnoi-2017 题目大意:给定一个$n$个数的序列$a$,求满足一下情况的点对个数: 注释:$1\le n,m\le 2\cdot 10^5$,$1\le p1,p2\l ...
- bzoj4826 [Hnoi2017]影魔
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...
- BZOJ:4826: [Hnoi2017]影魔
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...
- HNOI2017影魔
影魔 这么简单的方法尽然想不到,我是真的菜 对每个点,用单调栈的方式处理出他左右第一个比他大的数的位置,你可以把\(0\)和\(n+1\)设成\(inf\). 显然对于每对\(lef[i]\)和\(r ...
随机推荐
- 第六次作业:Alpha阶段综合报告(Java-Team)
团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://github.com/WHUSE201 ...
- 【Alpha版本】冲刺阶段 - Day7 - 靠泊
Alpha:指集成了主要功能的第一个试用版本.在这个版本中有些小功能并未实现.事实上很多软件的 Alpha 版本只是在内部使用.给外部用户使用的 Alpha 版本会起一个比较美妙的名字,例如,技术预览 ...
- linux 下 nc 命令的使用
netcat被誉为网络安全界的'瑞士军刀',一个简单而有用的工具,透过使用TCP或UDP协议的网络连接去读写数据.它被设计成一个稳定的后门工具,能够直接由其它程序和脚本轻松驱动.同时,它也是一个功能强 ...
- 微信支付get_brand_wcpay_request:fail
最近做了微信支付功能,和后端一起踩坑中,微信一直报错:get_brand_wcpay_request:fail 出现该问题的原因: 1.生成的sign签名有问题 2.支付授权目录配置有问题 在经过仔细 ...
- python入门(12)dict
python入门(12)dict Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度. 举个例 ...
- 搭建ssm框架,可实现登录和数据展示以及增删改查
需求: 后台使用ssm(spring-springMVC-mybatis)进行整合 前台使用bootstrap框架 前后台交互使用Ajax进行发送 表结构: 登录页面后显示所有用户信息,可对每条进行增 ...
- MongoDB系列四(索引).
一.索引简介 再来老生常谈一番,什么是索引呢?数据库索引与书籍的索引类似.有了索引就不需要翻整本书,数据库可以直接在索引中查找,在索引中找到条目以后,就可以直接跳转到目标文档的位置,这能使查找速度提高 ...
- JSON的简单书写(初学),使用Java语言反序列化
这个适合初学者:刚刚我学习的 1.基础的"JSON" 对象是用一对大括号: 例如: { "name":"xiaohua", ...
- DOM常用外部插入方法与区别
1.DOM外部插入after()与before() 节点与节点之前有各种关系,除了父子,祖辈关系,还可以是兄弟关系.之前我们在处理节点插入的时候,接触到了内部插入的几个方法,这节我们开始讲外部插入的处 ...
- python 资产管理
python 资产管理 一.Agent 方式 1.这个方法的优点:使用简单,速度快,适合服务器较多场景使用,缺点:服务器比较占资源,性能会变低. 2.使用Agent的前提条件是客户端(服务器)特别多的 ...