博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[HNOI2017/AHOI2017]影魔
阅读量:4574 次
发布时间:2019-06-08

本文共 2997 字,大约阅读时间需要 9 分钟。

Description:

奈文摩尔有 \(n\) 个灵魂,他们在影魔宽广的体内可以排成一排,从左至右标号 \(1\)\(n\)。第 \(i\) 个灵魂的战斗力为 \(k_i\),灵魂们以点对的形式为影魔提供攻击力。对于灵魂对 \(i, j\) 来说,若不存在 \(k_s\\) 大于 \(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 lt; c lt; k_i\),则会为影魔提供 \(p_2\) 的攻击力,当这样的 \(c\) 不存在时,自然不会提供这 \(p_2\) 的攻击力;其他情况的点对,均不会为影魔提供攻击力。

影魔的挚友噬魂鬼在一天造访影魔体内时被这些灵魂吸引住了,他想知道,对于任意一段区间 \([a, b]\),位于这些区间中的灵魂对会为影魔提供多少攻击力,即考虑所有满足 \(a\le ilt;j\le b\) 的灵魂对 \(i, j\) 提供的攻击力之和。
顺带一提,灵魂的战斗力组成一个 \(1\)\(n\) 的排列:\(k_1, k_1, \cdots, k_n\)

Hint:

对于 \(30\%\) 的数据,\(1\le n, m\le 500\)

另有 \(30\%\) 的数据,\(p_1 = 2p_2\)
对于 \(100\%\) 的数据,\(1\le n,m\le 200000, 1\le p_1, p_2\le 1000\)

Solution:

这题直接统计不好统计

我们反过来考虑每个位置对区间的贡献

首先预处理出每个位置左右第一个大于它的位置

1.\(i​\)对于区间(\(l[i] ,r[i]​\)),有\(p_1​\)的贡献,我们在扫到\(r[i]​\)更新\(l[i]​\)即可

2.\(i\)对于所有区间\((l[i],i+1 \text{~} r[i]-1)\)\(p_2\)的贡献,我们在扫到\(l[i]\)时更新\(i+1 \text{~} r[i]-1\)

3.\(i​\)对于所有区间\((l[i]+1\text{~}i-1,r[i])​\)\(p_2​\)的贡献,我们在扫到\(r[i]​\)时更新\(l[i]+1\text{~}i-1​\)

然后把询问离线拆成\(l,r\)后按端点排序,每次询问区间\(l~r\)的和,答案就是两次询问相减

注意要特判相邻位置的贡献

update:

今天体育课ysbs给我讲了一个更优秀的方法,实际上没必要处理出每个点的左右边界
对于贡献2,我们只要枚举所有以该点为右端点的区间,单调栈维护最近的大于该点的位置
分为左大于右和左小于右两种情况分别做一次就行,这样稍微方便一些

#include #include 
#include
#include
#include
#include
#include
#include
#include
#include
#define ls p<<1 #define rs p<<1|1using namespace std;typedef long long ll;const ll mxn=1e6+5;ll n,m,p1,p2,tot,cnt1,cnt2,a[mxn],lt[mxn],rt[mxn],ans[mxn];ll hd1[mxn],hd2[mxn],tr[mxn<<2],tag[mxn<<2];struct Q { ll pos,l,r,id; }q[mxn];struct ed { ll to1,to2,nxt;}t1[mxn],t2[mxn];inline ll read() { char c=getchar(); ll x=0,f=1; while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();} while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();} return x*f;}inline ll chkmax(ll &x,ll y) {if(x
y) x=y;}ll cmp(Q x,Q y) { return x.pos
>1; tr[ls]+=(mid-l+1)*tag[p]; tr[rs]+=(r-mid)*tag[p]; tag[ls]+=tag[p]; tag[rs]+=tag[p]; tag[p]=0; }}void update1(ll l,ll r,ll pos,ll val,ll p){ if(l==r) { tr[p]+=val; return ; } ll mid=(l+r)>>1; push_down(l,r,p); if(pos<=mid) update1(l,mid,pos,val,ls); else update1(mid+1,r,pos,val,rs); push_up(p);}void update2(ll l,ll r,ll ql,ll qr,ll val,ll p){ if(ql<=l&&r<=qr) { tr[p]+=val*(r-l+1); tag[p]+=val; return ; } ll mid=(l+r)>>1; push_down(l,r,p); if(ql<=mid) update2(l,mid,ql,qr,val,ls); if(qr>mid) update2(mid+1,r,ql,qr,val,rs); push_up(p);}ll query(ll l,ll r,ll ql,ll qr,ll p){ if(ql<=l&&r<=qr) return tr[p]; ll mid=(l+r)>>1; push_down(l,r,p); ll res=0; if(ql<=mid) res+=query(l,mid,ql,qr,ls); if(qr>mid) res+=query(mid+1,r,ql,qr,rs); return res;}int main(){ n=read(); m=read(); p1=read(); p2=read(); ll l,r; for(ll i=1;i<=n;++i) a[i]=read(); for(ll i=1;i<=m;++i) { l=read(),r=read(); q[i]=(Q){l-1,l,r,i}; q[i+m]=(Q){r,l,r,i+m}; } stack
st; for(ll i=1;i<=n;++i) { while(!st.empty()&&a[st.top()]
=1;--i) { while(!st.empty()&&a[st.top()]

转载于:https://www.cnblogs.com/list1/p/10520711.html

你可能感兴趣的文章
js中for和while运行速度比较
查看>>
算法第5章作业
查看>>
7.9 练习
查看>>
基于ArcGIS JS API的在线专题地图实现
查看>>
learnByWork
查看>>
lua 函数
查看>>
Git的基本命令
查看>>
四平方和
查看>>
第十八周 12.27-1.2
查看>>
C# IP地址字符串和数值转换
查看>>
TCHAR和CHAR类型的互转
查看>>
常用界面布局
查看>>
C语言—— for 循环
查看>>
IBM lotus9.0测试版即将公测
查看>>
xml常用方法
查看>>
Cube Stacking(并差集深度+结点个数)
查看>>
AndroidStudio3更改包名失败
查看>>
jq 删除数组中的元素
查看>>
js URL中文传参乱码
查看>>
Leetcode 367. Valid Perfect Square
查看>>