(二分)P7405 [JOI 2021 Final] 雪玉 题解
思路
由于雪球之间的相对位置是不会改变的,所以对于一个雪球,越过相邻的雪球的初始位置一定不会令其变大。
如果雪球的滚动范围没有交集,答案显然就是区间长度。但如果有了交集,我们必须判断哪个雪球先滚到,一个区间便分为了分属左右两雪球的两个区间,于是就要找出两边最后一次不交的那个断点。
由于断点具有单调性,直接二分启动。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=2e5+5;
ll n,q;
ll a[maxn],w[maxn];
ll L[maxn],R[maxn],ans[maxn];
void solve(ll x,ll len) {
if(L[q]+R[q]<=len) {
ans[x]+=R[q];
ans[x+1]+=L[q];
return;
}
ll l=1,r=q;
while(l<r) {
ll mid=(l+r)/2;
if(L[mid]+R[mid]>len)
r=mid;
else
l=mid+1;
}
if(L[l]==L[l-1]) {
ans[x]+=len-L[l];
ans[x+1]+=L[l];
} else {
ans[x]+=R[l];
ans[x+1]+=len-R[l];
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
for(ll i=1; i<=n; i++)
cin>>a[i];
ll sum=0;
for(ll i=1; i<=q; i++) {
cin>>w[i];
sum+=w[i];
L[i]=max(L[i-1],-sum),R[i]=max(R[i-1],sum);
}
ans[1]+=L[q],ans[n]+=R[q];
for(ll i=1; i<n; i++)
solve(i,a[i+1]-a[i]);
for(ll i=1; i<=n; i++)
cout<<ans[i]<<endl;
return 0;
}