[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 ...
随机推荐
- 201621123050 《Java程序设计》第13周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户通过网 ...
- java web 初学
我希望在本学期本堂课上学会使用java web 框架 精通mvc架构模式 学会通过框架和数据库对产品进行构造与编写. 我计划每周用16小时的时间进行学习java web 一周4学时上课时间 周一到周五 ...
- 201621123057 《Java程序设计》第10周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7-1回答 1.1 自己以前编写的代码中经常出现什 ...
- python 实现cm批量上传
import requests import json import time import random url = 'http://cm.admin.xxxx.com/customer/aj_ad ...
- ThreadLocal就是这么简单
前言 今天要研究的是ThreadLocal,这个我在一年前学习JavaWeb基础的时候接触过一次,当时在baidu搜出来的第一篇博文ThreadLocal,在评论下很多开发者认为那博主理解错误,给出了 ...
- Hadoop学习笔记一(HDFS架构)
介绍 Hadoop分布式文件系统(HDFS)设计的运行环境是商用的硬件系统.他和现存的其他分布式文件系统存在很多相似点.不过HDFS和其他分布式文件系统的区别才是他的最大亮点,HDFS具有高容错的特性 ...
- CRC 校验
匠心零度 转载请注明原创出处,谢谢! 说明 上篇RocketMQ(二):RPC通讯介绍了rocketmq的一些rpc细节,其实这些内容不仅仅是rocketmq内容,任何通信模块基本都是类似的,这块内容 ...
- zuul入门(3)开发zuul的过滤器
1.编写Zuul过滤器(Java&Groovy) 理解过滤器类型和请求生命周期后,我们来编写一个Zuul过滤器.编写Zuul的过滤器非常简单,我们只需继承抽象类ZuulFilter,然后实现几 ...
- linux下查看mysql日志文件的方法
查看mysql日志方法: mysql默认不允许我们查看日志.需要更改一些设置 1 vi 更改配置文件 允许用户查看日志文件 sudo vi /etc/mysql/mysql.conf.d/mysqld ...
- Python之面向对象二
面向对象的三大特性: 继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 python中类的继承分为:单继承和多继承 c ...