bzoj千题计划196:bzoj4826: [Hnoi2017]影魔
http://www.lydsy.com/JudgeOnline/problem.php?id=4826
吐槽一下bzoj这道题的排版是真丑。。。
我还是粘洛谷的题面吧。。。
提供p1的攻击力:i,j 位置的数是区间[i,j]的最大值和次大值
提供p2的攻击力:i,j位置的数有一个是区间[i,j]的最大值,另一个不是次大值
记录L[i]、R[i] 分别表示i左右第一个大于k[i]的位置
p1的贡献:
1、点对(L[i],R[i]) 2、点对(i,i+1)
p2的贡献:
1、点对(L[i],i+1),(L[i],i+2),……,(L[i],R[i]-1) 这些区间的最大值在L[i],次大值在i
2、点对(i-1,R[i]),(i-2,R[i]),……,(L[i+1],R[i]) 这些区间的最大值在R[i],次大值在i
然后问题就变成了
二维平面上单点修改,区间修改,矩阵查询
主席树(或许它叫可持久化线段树)可搞
第i颗线段树维护前i行的信息
主席树实现区间修改时出现了个bug,调了一下午+一晚上~~~~(>_<)~~~~
上面的写法是不对的,第4行,当区间被包含时,lc,rc 赋不上值,可能会丢失之前的部分信息
改成这样就好啦


#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; #define N 200001 typedef long long LL; int a[N]; int st[N][],top;
int L[N],R[N]; struct node
{
int x,y;
}A[N]; struct node2
{
int x,yl,yr;
}B[N<<]; LL num; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} int root[][N]; struct TREE
{
int lc[N*],rc[N*];
LL sum[N*];
int tag[N*];
int tot; void insert(int pre,int &k,int l,int r,int opl,int opr)
{
k=++tot;
tag[k]=tag[pre];
sum[k]=sum[pre]+opr-opl+;
lc[k]=lc[pre];
rc[k]=rc[pre];
if(l>=opl && r<=opr)
{
tag[k]++;
return;
}
int mid=l+r>>;
if(opr<=mid) insert(lc[pre],lc[k],l,mid,opl,opr);
else if(opl>mid) insert(rc[pre],rc[k],mid+,r,opl,opr);
else
{
insert(lc[pre],lc[k],l,mid,opl,mid);
insert(rc[pre],rc[k],mid+,r,mid+,opr);
}
} void query(int x,int pre,int l,int r,int opl,int opr)
{
if(l>=opl && r<=opr)
{
num+=sum[x]-sum[pre];
return;
}
int mid=l+r>>;
if(opr<=mid)
{
num+=(tag[x]-tag[pre])*(opr-opl+);
query(lc[x],lc[pre],l,mid,opl,opr);
}
else if(opl>mid)
{
num+=(tag[x]-tag[pre])*(opr-opl+);
query(rc[x],rc[pre],mid+,r,opl,opr);
}
else
{
num+=(tag[x]-tag[pre])*(mid-opl+);
query(lc[x],lc[pre],l,mid,opl,mid);
num+=(tag[x]-tag[pre])*(opr-mid);
query(rc[x],rc[pre],mid+,r,mid+,opr);
}
} }tr[]; bool cmp1(node p,node q)
{
return p.x<q.x;
} bool cmp2(node2 p,node2 q)
{
return p.x<q.x;
} int main()
{
//freopen("sf1.in","r",stdin);
//freopen("my.out","w",stdout);
int n,m,p1,p2;
read(n); read(m); read(p1); read(p2);
for(int i=;i<=n;++i) read(a[i]);
st[top][]=n+;
st[top][]=;
for(int i=;i<=n;++i)
{
while(top && a[i]>st[top][]) top--;
L[i]=st[top][];
st[++top][]=a[i];
st[top][]=i;
}
st[top=][]=n+;
st[top][]=n+;
for(int i=n;i;--i)
{
while(top && a[i]>st[top][]) top--;
R[i]=st[top][];
st[++top][]=a[i];
st[top][]=i;
}
int cnt=;
for(int i=;i<=n;++i)
if(L[i] && R[i]<=n)
{
A[++cnt].x=L[i];
A[cnt].y=R[i];
}
sort(A+,A+cnt+,cmp1);
int now=;
for(int i=;i<=cnt;++i)
{
while(now+<A[i].x) root[][now+]=root[][now],now++;
tr[].insert(root[][now],root[][A[i].x],,n,A[i].y,A[i].y);
now=A[i].x;
}
while(now!=n) root[][now+]=root[][now++];
cnt=;
for(int i=;i<=n;++i)
{
if(R[i]!=i+ && L[i])
{
B[++cnt].x=L[i];
B[cnt].yl=i+;
B[cnt].yr=R[i]-;
}
if(L[i]!=i- && R[i]<=n)
{
B[++cnt].x=R[i];
B[cnt].yl=L[i]+;
B[cnt].yr=i-;
}
}
sort(B+,B+cnt+,cmp2);
now=;
for(int i=;i<=cnt;++i)
{
while(now+<B[i].x) root[][now+]=root[][now],now++;
tr[].insert(root[][now],root[][B[i].x],,n,B[i].yl,B[i].yr);
now=B[i].x;
if(tr[].tag[])
{
int as=;
}
}
while(now!=n) root[][now+]=root[][now++];
int l,r;
LL ans;
while(m--)
{
read(l); read(r);
num=;
tr[].query(root[][r],root[][l-],,n,l,r);
ans=num*p1;
num=;
tr[].query(root[][r],root[][l-],,n,l,r);
ans+=num*p2;
ans+=(r-l)*p1;
cout<<ans<<'\n';
}
}
题目背景
影魔,奈文摩尔,据说有着一个诗人的灵魂。 事实上,他吞噬的诗人灵魂早已成千上万。
千百年来,他收集了各式各样的灵魂,包括诗人、 牧师、 帝王、 乞丐、 奴隶、 罪人,当然,还有英雄。
题目描述
每一个灵魂,都有着自己的战斗力,而影魔,靠这些战斗力提升自己的攻击。
奈文摩尔有 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 个询问。
输入输出样例
说明
30%: 1<= n,m <= 500。
另 30%: p1=2*p2。
100%:1 <= n,m <= 200000; 1 <= p1,p2 <= 1000。
bzoj千题计划196:bzoj4826: [Hnoi2017]影魔的更多相关文章
- bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块
http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...
- bzoj千题计划303:bzoj4827: [Hnoi2017]礼物
https://www.lydsy.com/JudgeOnline/problem.php?id=4827 式子化简一下,发现最后只跟 Σ xi*yi 有关 第二个序列反转,就可以用FFT优化 注意: ...
- bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪
http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...
- bzoj千题计划177:bzoj1858: [Scoi2010]序列操作
http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...
- bzoj千题计划317:bzoj4650: [Noi2016]优秀的拆分(后缀数组+差分)
https://www.lydsy.com/JudgeOnline/problem.php?id=4650 如果能够预处理出 suf[i] 以i结尾的形式为AA的子串个数 pre[i] 以i开头的形式 ...
- bzoj千题计划304:bzoj3676: [Apio2014]回文串(回文自动机)
https://www.lydsy.com/JudgeOnline/problem.php?id=3676 回文自动机模板题 4年前的APIO如今竟沦为模板,,,╮(╯▽╰)╭,唉 #include& ...
- bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹
http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len ...
- bzoj千题计划278:bzoj4590: [Shoi2015]自动刷题机
http://www.lydsy.com/JudgeOnline/problem.php?id=4590 二分 这么道水题 没long long WA了两发,没判-1WA了一发,二分写错WA了一发 最 ...
- bzoj千题计划250:bzoj3670: [Noi2014]动物园
http://www.lydsy.com/JudgeOnline/problem.php?id=3670 法一:KMP+st表 抽离nxt数组,构成一棵树 若nxt[i]=j,则i作为j的子节点 那么 ...
随机推荐
- 接口自动化测试框架-AIM
最近在做公司项目的自动化接口测试,在现有几个小框架的基础上,反复研究和实践,搭建了新的测试框架.利用业余时间,把框架总结了下来. AIM框架介绍 AIM,是Automatic Interface Mo ...
- Unity利用SMSSDK实现短信验证码(附代码)
最近一直在研究如何给app更多实用性的功能,在app进行登录或者注册时,为了方便用户更加快捷的完成登录功能,所以就决定采用短信验证码的方式进行验证登录.在学习的过程中,先使用了Mob的短信服务进行短信 ...
- Siki_Unity_2-9_C#高级教程(未完)
Unity 2-9 C#高级教程 任务1:字符串和正则表达式任务1-1&1-2:字符串类string System.String类(string为别名) 注:string创建的字符串是不可变的 ...
- mysql学习(3)10045错误,连接不上数据库
mysql8.0默认加密的方式是caching_sha2_password认证方式,当使用navicat 或者程序连接是连接不上, 好吧,那我们修改配置并重启服务可以解决此问题 找到mysql的配置文 ...
- mysql学习(2)-Navicat Premium 12 链接MySQL8.0.11数据库报2059错误
Navicat Premium 12 链接MySQL8.0.11数据库报2059错误 1,问题现象 安装完MySQL8.0.11和Navicat Premium12后,我们会用Navicat去测试连接 ...
- PAT甲题题解-1127. ZigZagging on a Tree (30)-中序、后序建树
根据中序遍历和前序遍历确定一棵二叉树,然后按“层次遍历”序列输出.输出规则:除根节点外,接下来每层的节点输出顺序是:先从左到右,再从右到左,交替输出 #include <iostream> ...
- Linux读书笔记第三、四章
第三章 主要内容: 进程和线程 进程的生命周期 进程的创建 进程的终止 1. 进程和线程 进程和线程是程序运行时状态,是动态变化的,进程和线程的管理操作(比如,创建,销毁等)都是有内核来实现的. Li ...
- VS社区版 使用 OpenCover 获取测试代码覆盖率
注:暂不支持VS2017 Visual Studio 2015 社区版没有集成代码覆盖率的功能,所以想在VS社区版中获取单元测试的代码覆盖率等数据,需要使用到插件 OpenCover. 下载 Open ...
- 这个C#程序真了不起
(1)在2~31中,这个数不能且仅不能被两个相邻数整除 (2)2 123 581 660 200 (2,3,4,5,6,7,8,9,10,11,12,13,14,15,18,19,20,21,22,2 ...
- Installing OpenSSH from the Settings UI on Windows Server 2019 or Windows 10 1809
Installing OpenSSH from the Settings UI on Windows Server 2019 or Windows 10 1809 OpenSSH client and ...