P10083 [GDKOI2024 提高组] 不休陀螺 题解
题目传送门
前言
赛时感觉 6 道题唯一可以做出的题,但是赛后感觉除了三个黑题,其他也可以做一下的。看来是有场切蓝题的能力的 awa。
题解部分
考虑一个区间
-
打完一轮之后不能亏费。
-
最低的情况也需要保持
\ge 0 。
对于第一种情况显然很好做,记录一个前缀和即可。对于第二种情况我们考虑如何快速的找到一个区间中最低的情况(找到谷)。对于
时间复杂度为
可以发现,当
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
#define ll long long
ll inline read()
{
ll num=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='0')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){num=(num<<3)+(num<<1)+(ch^48);ch=getchar();}
return num*f;
}
int n;ll E,ans;
ll a[N],b[N],d[N],s[N],p[N],sd[N];
struct STable
{
ll st[22][N];
void build()
{
for(int i=1;i<=n;i++)st[0][i]=p[i];
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
st[i][j]=min(st[i-1][j],st[i-1][j+(1<<i-1)]);
}
ll ask(int l,int r)
{
int t=__lg(r-l+1);
return min(st[t][l],st[t][r-(1<<t)+1]);
}
}ST;
#define lb (x&-x)
struct BIT
{
int t[N];
void add(int x,int v){while(x<=n+1)t[x]+=v,x+=lb;}
int ask(int x){int res=0;while(x)res+=t[x],x-=lb;return res;}
}T;
ll c[N];
void discret(ll A[N])
{
for(int i=0;i<=n;i++)c[i]=A[i];
sort(c,c+1+n);int l=unique(c,c+1+n)-c-1;
for(int i=0;i<=n;i++)A[i]=lower_bound(c,c+1+l,A[i])-c+1;
}
int main(){
n=read();E=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)b[i]=read();
for(int i=1;i<=n;i++)
{
d[i]=min(0ll,b[i]-a[i]);
s[i]=s[i-1]+b[i]-a[i];
p[i]=-a[i]-d[i];
sd[i]=sd[i-1]+d[i];
}
discret(s);ST.build();
for(int L=1,R=1;L<=n;L++)
{
ll sum=sd[R]-sd[L-1],mn=ST.ask(L,R);
while(R<=n)
{
if(sum+mn+E>=0)T.add(s[R++],1),sum+=d[R],mn=min(mn,p[R]);
else break;
}
ans+=R-L-T.ask(s[L-1]-1);
if(L==R)R++;else T.add(s[L],-1);
}
printf("%lld",ans);
return 0;
}
My Stupid Mistake
赛时
赛后再码一遍(没有原来代码了)有如下错误:
-
const int N=2e5+5;超好习惯。 -
ST 表写挂了。
-
int ans;不开 long long 见祖宗。最简单的问题却总是在我发完帖才发现的。