GDKOI-S 2024 Day2T1 不休陀螺
现场做了,离散化数组没开 ll,被卡 au 线 \(\to\) 卡线 ag。
因为代码是半个月前写的了,回忆做法时可能有点偏差,如果发现有误请联系我修改。😃
考虑怎么刻画题目所给条件。发现对于一个区间 \([l,r]\),可以钦定其中一个卡牌 \(i\),使得这张卡牌是第一张无法打出的牌。然后考虑它前面放什么牌,会发现前面会放所有 \(a_i>b_i\) 的牌。
然后用形式化语言刻画可以无限取下去的条件。设 \(c_i=a_i-b_i\),则一个区间可行,可以分成两种情况。
-
钦定的牌 \(a_i\leq b_i\) 时,\(\not\exists i, E-\sum\limits_{j\in[l,r]\land c_j>0}c_j<a_i\)。
-
否则,\(\not\exists i,E-\sum\limits_{j\in[l,r]\land c_j>0}c_j+a_i-b_i<a_i\) 即 \(E-\sum\limits_{j\in[l,r]\land c_j>0}c_j<b_i\)。
-
任何情况下,\(\sum\limits_{i\in[l,r]} c_i\ge 0\),否则一定无法无限取。
感性与理性并用地理解容易发现前面两个限制是满足单调性的,原因显然。于是想到固定右端点 \(r\),二分 \(l\)。但是又有一个问题:因为 \(c_i\) 不一定非负,所以这些所有限制并不是满足单调性的。于是考虑对于每个右端点,求出极大区间 \([L_i,R_i]\),再用前缀和 \(s_i=\sum_{j\le i}c_j\) 转化一下第三个限制,则一个区间 \([l,r]\) 符合条件的限制条件变成:
\[L_r\le l\le R_r\land s_r\ge s_{l-1}
\]
这显然是一个二维数点问题,扫描线解决。时间复杂度 \(O(n\log n)\)。
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;
}

浙公网安备 33010602011771号