GDKOI-S 2024 Day2T1 不休陀螺
现场做了,离散化数组没开 ll,被卡 au 线
因为代码是半个月前写的了,回忆做法时可能有点偏差,如果发现有误请联系我修改。😃
考虑怎么刻画题目所给条件。发现对于一个区间
然后用形式化语言刻画可以无限取下去的条件。设
-
钦定的牌
时, 。 -
否则,
即 。 -
任何情况下,
,否则一定无法无限取。
感性与理性并用地理解容易发现前面两个限制是满足单调性的,原因显然。于是想到固定右端点
这显然是一个二维数点问题,扫描线解决。时间复杂度
code:
点击查看代码
bool Mbe;
int n,m,a[N],b[N];
ll s[N],A[N],B[N],d[N];
vector<int> g[N];
struct STable{
int st[2][N][23],lg[N],pw[107];
void init(){
rep(i,1,n){
st[0][i][0]=st[1][i][0]=-inf;
if(a[i]>b[i])st[0][i][0]=b[i];
else st[1][i][0]=a[i];
}
rep(i,2,n)lg[i]=lg[i>>1]+1;
rep(i,0,30)pw[i]=1<<i;
rep(j,1,lg[n]){
rep(i,1,n-pw[j]+1){
rep(k,0,1)st[k][i][j]=max(st[k][i][j-1],st[k][i+pw[j-1]][j-1]);
}
}
}
il int qryMax(int l,int r,int p){
int k=lg[r-l+1];
return max(st[p][l][k],st[p][r-pw[k]+1][k]);
}
}T;
struct BIT{
int tr[N];
#define lb(x) (x&(-x))
il void upd(int x,int y){while(x<=n)tr[x]+=y,x+=lb(x);}
il int qry(int x){int ret=0;while(x)ret+=tr[x],x-=lb(x);return ret;}
#undef lb
}R;
il bool check(int l,int r){
if(T.qryMax(l,r,1)>m-s[r]+s[l-1])return 0;
if(T.qryMax(l,r,0)>m-s[r]+s[l-1])return 0;
return 1;
}
void Yorushika(){
scanf("%d%d",&n,&m);
rep(i,1,n)a[i]=read(),A[i]=A[i-1]+a[i];
rep(i,1,n)b[i]=read(),B[i]=B[i-1]+b[i];
rep(i,1,n){
s[i]=s[i-1];
if(a[i]>b[i])s[i]+=a[i]-b[i];
}
T.init();
rep(i,1,n)d[i]=A[i]-B[i];
d[n+1]=0;
sort(d+1,d+n+2);
int k=unique(d+1,d+n+2)-d-1;
rep(i,1,n){
int l=1,r=i,res=i+1;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid,i))r=(res=mid)-1;
else l=mid+1;
}
int p=lower_bound(d+1,d+k+1,A[i]-B[i])-d;
g[res-1].eb(p);
}
R.upd(lower_bound(d+1,d+k+1,0)-d,1);
ll ans=0;
rep(i,1,n){
int p=lower_bound(d+1,d+k+1,A[i]-B[i])-d;
for(int j:g[i])ans-=i-R.qry(j-1);
ans+=i-R.qry(p-1),R.upd(p,1);
}
printf("%lld\n",ans);
}
bool Med;
signed main(){
freopen("top.in","r",stdin);
freopen("top.out","w",stdout);
int t=1;
// scanf("%d",&t);
while(t--)Yorushika();
// cerr<<1.*(&Mbe-&Med)/1024/1024;
}