P11699 [ROIR 2025] 酸雨 Solution
模拟赛遇到的,共计 7k 的友好题目。
题解
将题目转化一下:每次给定你一个区间,定义
对于区间的处理,考虑用线段树解决。
具体的,考虑在每次输入后,通过线段树二分处理出所合并的区间,对于区间之后的值全部减一即可。
但原题支持
考虑到
发现对于一个区间
思考后发现
对于寻找这个点,依旧线段树解决即可。
考虑如何处理出
考虑把
考虑单个
对于
对于以上的三颗线段树都可以融成一颗(避免 MLE)。
总体复杂度
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>
#ifdef _WIN32
#define getchar _getchar_nolock
#define putchar _putchar_nolock
#else
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#endif
#define pll pair<ll,ll>
#define pld pair<ld,ld>
typedef long long ll;
typedef long double ld;
typedef __int128 i128;
namespace io {
using namespace std;
template <typename T> void debug (T x) {
cerr<<x<<'\n';
}
template <typename T> void debuglen (T x) {
cerr<<x<<' ';
}
template <typename T,typename...Args> void debug (T x,Args...args) {
cerr<<x<<' ';
debug(args...);
}
template <typename T> void debug (T *lt,T *rt) {
ll len=rt-lt;
for (ll i=0;i<len;i++) {
debuglen(*(lt+i));
}
cerr<<'\n';
}
inline ll read () {
char x=getchar();
ll ans=0,f=1;
while (x<'0'||x>'9') {
if (x=='-') {
f=-1;
}
x=getchar();
}
while (x>='0'&&x<='9') {
ans=(ans<<1)+(ans<<3);
ans+=(x^'0');
x=getchar();
}
return ans*f;
}
void print (ll x) {
if (x<0) {
x=-x;
putchar('-');
}
if (x>=10) {
print(x/10);
}
putchar(x%10+'0');
}
}
using namespace io;
const ll N=1e5+5,mod=1e9+7,inf=2e18;
const ld eps=1e-6;
struct node {
ll l,r;
} q[N];
ll n,a[N],ans[N],sum[N];
ll st[N],top;
vector<pll> vl[N],vr[N];
struct Segtree {
ll t[N<<2],lt[N<<2];
inline void push_up (ll pos) {
t[pos]=t[pos<<1]+t[pos<<1|1];
}
inline void push_down (ll pos) {
if (!lt[pos]) {
return ;
}
t[pos<<1]+=lt[pos];
t[pos<<1|1]+=lt[pos];
lt[pos<<1]+=lt[pos];
lt[pos<<1|1]+=lt[pos];
lt[pos]=0;
}
void build (ll pos,ll l,ll r) {
if (l==r) {
t[pos]=l;
return ;
}
ll mid=(l+r)>>1;
build(pos<<1,l,mid);
build(pos<<1|1,mid+1,r);
push_up(pos);
}
inline void push_upl (ll pos) {
t[pos]=t[pos<<1];
if (a[t[pos<<1|1]]>a[t[pos]]) {
t[pos]=t[pos<<1|1];
}
}
void rebuild (ll pos,ll l,ll r) {
if (l==r) {
t[pos]=l;
return ;
}
ll mid=(l+r)>>1;
rebuild(pos<<1,l,mid);
rebuild(pos<<1|1,mid+1,r);
push_upl(pos);
}
void rerebuild (ll pos,ll l,ll r) {
lt[pos]=0;
if (l==r) {
t[pos]=0;
return ;
}
ll mid=(l+r)>>1;
rerebuild(pos<<1,l,mid);
rerebuild(pos<<1|1,mid+1,r);
push_up(pos);
}
ll ask (ll pos,ll l,ll r,ll L,ll R) {
if (L<=l&&r<=R) {
return t[pos];
}
ll mid=(l+r)>>1,cnt=0;
if (L<=mid) {
cnt=ask(pos<<1,l,mid,L,R);
}
if (R>mid) {
ll kl=ask(pos<<1|1,mid+1,r,L,R);
if (!cnt||a[cnt]<a[kl]) {
cnt=kl;
}
}
return cnt;
}
void add (ll pos,ll l,ll r,ll L,ll R) {
if (L<=l&&r<=R) {
t[pos]--;
lt[pos]--;
return ;
}
ll mid=(l+r)>>1;
push_down(pos);
if (L<=mid) {
add(pos<<1,l,mid,L,R);
}
if (R>mid) {
add(pos<<1|1,mid+1,r,L,R);
}
push_up(pos);
}
ll query (ll pos,ll l,ll r,ll x) {
if (l==r) {
return t[pos];
}
ll mid=(l+r)>>1;
push_down(pos);
if (x<=mid) {
return query(pos<<1,l,mid,x);
}
return query(pos<<1|1,mid+1,r,x);
}
inline void push_downl (ll pos,ll l,ll r) {
ll mid=(l+r)>>1;
if (!lt[pos]) {
return ;
}
t[pos<<1]=lt[pos]*(mid-l+1);
t[pos<<1|1]=lt[pos]*(r-mid);
lt[pos<<1]=lt[pos<<1|1]=lt[pos];
lt[pos]=0;
}
void cover (ll pos,ll l,ll r,ll L,ll R,ll x) {
if (L<=l&&r<=R) {
lt[pos]=x;
t[pos]=x*(r-l+1);
return ;
}
ll mid=(l+r)>>1;
push_downl(pos,l,r);
if (L<=mid) {
cover(pos<<1,l,mid,L,R,x);
}
if (R>mid) {
cover(pos<<1|1,mid+1,r,L,R,x);
}
push_up(pos);
}
ll find (ll pos,ll l,ll r,ll L,ll R) {
if (L<=l&&r<=R) {
return t[pos];
}
ll mid=(l+r)>>1,cnt=0;
push_downl(pos,l,r);
if (L<=mid) {
cnt=find(pos<<1,l,mid,L,R);
}
if (R>mid) {
cnt+=find(pos<<1|1,mid+1,r,L,R);
}
return cnt;
}
} tr;
inline ll get_l (ll x) {
ll l=1,r=n,cnt=0;
while (l<=r) {
ll mid=(l+r)>>1;
if (tr.query(1,1,n,mid)>=x) {
cnt=mid;
r=mid-1;
}
else {
l=mid+1;
}
}
return cnt;
}
inline ll get_r (ll x) {
ll l=1,r=n,cnt=0;
while (l<=r) {
ll mid=(l+r)>>1;
if (tr.query(1,1,n,mid)<=x) {
cnt=mid;
l=mid+1;
}
else {
r=mid-1;
}
}
return cnt;
}
inline void solve () {
n=read();
for (ll i=1;i<=n;i++) {
a[i]=read();
sum[i]=sum[i-1]+a[i];
}
tr.build(1,1,n);
for (ll i=1;i<n;i++) {
ll x=read();
q[i]={get_l(x),get_r(x+1)};
tr.add(1,1,n,get_r(x)+1,n);
}
tr.rebuild(1,1,n);
for (ll i=1;i<n;i++) {
ll l=q[i].l,r=q[i].r,pos=0;
pos=tr.ask(1,1,n,l,r);
vl[l].push_back({i,pos});
vr[r].push_back({i,pos});
ans[i]=-a[pos]-sum[r]+sum[l-1];
}
tr.rerebuild(1,1,n);
top=0;
for (ll i=1;i<=n;i++) {
while (top&&a[st[top]]<a[i]) {
top--;
}
tr.cover(1,1,n,st[top]+1,i,a[i]);
for (auto it : vr[i]) {
ans[it.first]+=tr.find(1,1,n,it.second,i);
}
st[++top]=i;
}
tr.rerebuild(1,1,n);
top=0;
st[0]=n+1;
for (ll i=n;i;i--) {
while (top&&a[st[top]]<a[i]) {
top--;
}
tr.cover(1,1,n,i,st[top]-1,a[i]);
for (auto it : vl[i]) {
ans[it.first]+=tr.find(1,1,n,i,it.second);
}
st[++top]=i;
}
for (ll i=1;i<n;i++) {
print(ans[i]);
puts("");
}
}
int main () {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ll T=1;
// T=read();
while (T--) {
solve();
}
return 0;
}