正题
题目链接:https://www.luogu.com.cn/problem/P7408
题目大意
一个有n+1n+1n+1层的地牢,从iii到i+1i+1i+1层要AiA_iAi点能量,第iii层可以花费BiB_iBi获得111点能量。
mmm次询问从SiS_iSi层出发到第TiT_iTi层在能量上限为UiU_iUi的情况下至少需要花费多少。
1≤n,m≤2×1051\leq n,m\leq 2\times 10^51≤n,m≤2×105
解题思路
模型可以转换成坐标轴上有nnn个点,第iii个在AiA_iAi,考虑使用一个点获得的能量走的路就是这个点伸出的线覆盖的范围,然后使得范围乘上BiB_iBi的和最小。
考虑能量上限的限制其实就是每个点覆盖的范围不能超过自身的UiU_iUi格。
考虑一个点覆盖范围根据UiU_iUi变化的变化:
- 没有其他影响,自己正常延伸,此时覆盖范围为一个和UiU_iUi有关的一次函数
- 延伸到下一个比自己大的位置,不能继续延伸,此时为一个常数
- 上一个比自己小的数延伸过来,此时为一个单调下降的一次函数
- 完全被上一个比自己小的覆盖,此时为000
也就是意味着每个点只需要考虑前后两个比自己小的数分成若干种情况即可。
考虑倒序枚举点,然后用树状数组记录一次项系数的和与二次项系数的和。
对于结尾的限制,我们找到能到达终点的最后的点直接走向它,然后减去那个点的贡献即可。
时间复杂度O(nlogn)O(n\log n)O(nlogn)
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;
}