P7408-[JOI 2021 Final]ダンジョン 3【贪心,树状数组】
正题
题目链接:https://www.luogu.com.cn/problem/P7408
题目大意
一个有\(n+1\)层的地牢,从\(i\)到\(i+1\)层要\(A_i\)点能量,第\(i\)层可以花费\(B_i\)获得\(1\)点能量。
\(m\)次询问从\(S_i\)层出发到第\(T_i\)层在能量上限为\(U_i\)的情况下至少需要花费多少。
\(1\leq n,m\leq 2\times 10^5\)
解题思路
模型可以转换成坐标轴上有\(n\)个点,第\(i\)个在\(A_i\),考虑使用一个点获得的能量走的路就是这个点伸出的线覆盖的范围,然后使得范围乘上\(B_i\)的和最小。
考虑能量上限的限制其实就是每个点覆盖的范围不能超过自身的\(U_i\)格。
考虑一个点覆盖范围根据\(U_i\)变化的变化:
- 没有其他影响,自己正常延伸,此时覆盖范围为一个和\(U_i\)有关的一次函数
- 延伸到下一个比自己大的位置,不能继续延伸,此时为一个常数
- 上一个比自己小的数延伸过来,此时为一个单调下降的一次函数
- 完全被上一个比自己小的覆盖,此时为\(0\)
也就是意味着每个点只需要考虑前后两个比自己小的数分成若干种情况即可。
考虑倒序枚举点,然后用树状数组记录一次项系数的和与二次项系数的和。
对于结尾的限制,我们找到能到达终点的最后的点直接走向它,然后减去那个点的贡献即可。
时间复杂度\(O(n\log n)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#define ll long long
#define lowbit(x) (x&-x)
using namespace std;
const ll N=2e5+10,inf=1e18;
struct node{
ll l,r,u;
}q[N];
ll n,m,a[N],b[N],s[N],ans[N];
ll cnt,u[N],nxt[N],pre[N];
ll f[N][20],g[N][20],lg[N];
vector<ll> d[N],v[N];
stack<ll> st;
ll rmqf(ll l,ll r){
ll z=lg[r-l+1];
l=f[l][z];r=f[r-(1<<z)+1][z];
return (b[l]<b[r])?l:r;
}
ll rmqg(ll l,ll r){
ll z=lg[r-l+1];
l=g[l][z];r=g[r-(1<<z)+1][z];
return (a[l]>a[r])?l:r;
}
struct TreeBinary{
ll t[N];
void Updata(ll x,ll val){
while(x<=cnt){
t[x]+=val;
x+=lowbit(x);
}
return;
}
ll Ask(ll x){
ll ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
void Change(ll l,ll r,ll val){
if(l>r)return;
l=lower_bound(u+1,u+1+cnt,l)-u;
r=upper_bound(u+1,u+1+cnt,r)-u;
Updata(l,val);Updata(r,-val);return;
}
}K,B;
signed main()
{
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++)scanf("%lld",&a[i]),s[i+1]=s[i]+a[i];
for(ll i=1;i<=n;i++)scanf("%lld",&b[i]);
for(ll i=2;i<=n+1;i++)lg[i]=lg[i>>1]+1;
for(ll i=1;i<=n+1;i++)f[i][0]=g[i][0]=i;
for(ll j=1;(1<<j)<=n+1;j++)
for(ll i=1;i+(1<<j)-1<=n+1;i++){
ll x=f[i][j-1],y=f[i+(1<<j-1)][j-1];
f[i][j]=(b[x]<b[y])?x:y;
x=g[i][j-1];y=g[i+(1<<j-1)][j-1];
g[i][j]=(a[x]>a[y])?x:y;
}
for(ll i=n;i>=1;i--){
while(!st.empty()&&b[i]<=b[st.top()])
{pre[st.top()]=i;st.pop();}
if(st.empty())nxt[i]=n+1;
else nxt[i]=st.top();
st.push(i);
}
for(ll i=1;i<=m;i++){
scanf("%lld%lld%lld",&q[i].l,&q[i].r,&q[i].u);u[i]=q[i].u;
ll las=lower_bound(s+1,s+1+n,s[q[i].r]-u[i])-s;
las=min(las,q[i].r-1);las=max(min(las,q[i].r-1),q[i].l);
las=rmqf(las,q[i].r-1);
v[q[i].l].push_back(i);
v[las].push_back(-i);
ans[i]+=(s[q[i].r]-s[las])*b[las];
}
sort(u+1,u+1+m);cnt=unique(u+1,u+1+m)-u-1;
for(ll i=n;i>=1;i--){
K.Change(0,s[nxt[i]]-s[i],b[i]);
B.Change(s[nxt[i]]-s[i]+1,inf,b[i]*(s[nxt[i]]-s[i]));
d[pre[i]].push_back(i);
for(ll j=0;j<d[i].size();j++){
ll x=d[i][j];
K.Change(s[x]-s[i],s[nxt[x]]-s[i],-b[x]);
B.Change(s[x]-s[i],s[nxt[x]]-s[i],b[x]*(s[x]-s[i]));
B.Change(s[nxt[x]]-s[i]+1,inf,-b[x]*(s[nxt[x]]-s[x]));
}
for(ll j=0;j<v[i].size();j++){
ll x=v[i][j],op=1;
if(x<0)x=-x,op=-op;
ll w=lower_bound(u+1,u+1+cnt,q[x].u)-u;
ans[x]+=op*(q[x].u*K.Ask(w)+B.Ask(w));
}
}
for(ll i=1;i<=m;i++){
if(a[rmqg(q[i].l,q[i].r-1)]>q[i].u)puts("-1");
else printf("%lld\n",ans[i]);
}
return 0;
}
P7408-[JOI 2021 Final]ダンジョン 3【贪心,树状数组】的更多相关文章
- Luogu P5103 「JOI 2016 Final」断层 树状数组or线段树+脑子
太神仙了这题... 原来的地面上升,可以倒着操作(时光倒流),转化为地面沉降,最后的答案就是每个点的深度. 下面的1,2操作均定义为向下沉降(与原题意的变换相反): 首先这个题目只会操作前缀和后缀,并 ...
- 【bzoj4240】有趣的家庭菜园 贪心+树状数组
题目描述 对家庭菜园有兴趣的JOI君每年在自家的田地中种植一种叫做IOI草的植物.JOI君的田地沿东西方向被划分为N个区域,由西到东标号为1~N.IOI草一共有N株,每个区域种植着一株.在第i个区域种 ...
- 贪心+树状数组维护一下 Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) D
http://codeforces.com/contest/724/problem/D 题目大意:给你一个串,从串中挑选字符,挑选是有条件的,按照这个条件所挑选出来的字符集合sort一定是最后选择当中 ...
- D 洛谷 P3602 Koishi Loves Segments [贪心 树状数组+堆]
题目描述 Koishi喜欢线段. 她的条线段都能表示成数轴上的某个闭区间.Koishi喜欢在把所有线段都放在数轴上,然后数出某些点被多少线段覆盖了. Flandre看她和线段玩得很起开心,就抛给她一个 ...
- [BZOJ4240]有趣的家庭菜园(贪心+树状数组)
最后数列一定是单峰的,问题就是最小化最后的位置序列的逆序对数. 从大到小加数,每次贪心看放左边和右边哪个产生的逆序对数更少,树状数组即可. 由于大数放哪对小数不产生影响,所以正确性显然. 注意相同数之 ...
- [P4064][JXOI2017]加法(贪心+树状数组+堆)
题目描述 可怜有一个长度为 n 的正整数序列 A,但是她觉得 A 中的数字太小了,这让她很不开心. 于是她选择了 m 个区间 [li, ri] 和两个正整数 a, k.她打算从这 m 个区间里选出恰好 ...
- [luoguP2672] 推销员(贪心 + 树状数组 + 优先队列)
传送门 贪心...蒟蒻证明不会... 每一次找最大的即可,找出一次最大的,数列会分为左右两边,左边用stl优先队列维护,右边用树状数组维护.. (线段树超时了....) 代码 #include < ...
- codeforces 1249 D2 Too Many Segments (hard version) 贪心+树状数组
题意 给定n个线段,线段可以相交,第\(i\)个线段覆盖的区间为\([l_i,r_i]\),问最少删除多少个线段让覆盖每个点的线段数量小于等于k. 分析 从左往右扫每个点\(x\),若覆盖点\(x\) ...
- [JZO6401]:Time(贪心+树状数组)
题目描述 小$A$现在有一个长度为$n$的序列$\{x_i\}$,但是小$A$认为这个序列不够优美. 小$A$认为一个序列是优美的,当且仅当存在$k\in [1,n]$,满足:$$x_1\leqsla ...
随机推荐
- 微软官方安装介质Windows10系统安装教程
微软官方安装介质Windows10系统安装教程 Jasper游戏 发布时间:04-2204:23 小贴士:事前准备 ★ 拥有 Internet 连接 ★ 在计算机.USB 或外部驱动器上拥有足够的可用 ...
- Docker创建Docker-Registry-私服
docker-compose.yml version: '3.1' services: registry: image: registry restart: always container_name ...
- rocketmq知识点
消息队列mq 参考资料:https://www.jianshu.com/p/824066d70da8 一.消息中间件的主要作用和功能: 1)异步解耦和分流: 2)挡住前端的数据洪峰,保证后端系统的稳定 ...
- Java规范化代码eclipse模板注释
建议下载阿里规范化插件 阿里的new java file的注释模板(Type): /** * @author ${user} * @date ${currentDate:date('YYYY/MM ...
- Buffer和Cache的异同
Buffer的本质是缓冲,常见实例如下面这个: 对,就是铁道端头那个巨大的弹簧一类的东西.作用是万一车没停住(是没停住啊,刹车了但是差一点没刹住那种,不是不拉刹直接撞上来),撞弹簧上减速降低危险,起到 ...
- Storm重启topology,失败
storm新加节点,重启topology后,出现错误 如果检查了CPU和内存不高后,还出现 java.lang.OutOfMemoryError: unable to create new nativ ...
- CentOS7中apache的部署与配置
一.apache的部署 输入命令 yum list | grep httpd 查看可安装的软件包,选择"httpd.x86_64"安装. 输入命令 yum install http ...
- Java反射的浅显理解
一.回顾反射相关的知识 1.在xml文件中使用反射的好处: 1)代码更加灵活,后期维护只需要修改配置文件即可 · 初学者一般习惯于在代码本身上直接修改,后期也可以修改配置文件达到相同的目的 · 修改配 ...
- 剑指 Offer 32 - I. 从上到下打印二叉树
剑指 Offer 32 - I. 从上到下打印二叉树 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 ...
- git clone 设置临时的 proxy
export ALL_PROXY=socks5://127.0.0.1:1086 git clone --depth 1 https://github.com/xxx/xxx.git unset AL ...