CF1439C 题解
题意
给定一个长度为 \(n\) 的非升序列 \(a\),有两类操作:
1 x y
,\(∀i∈[1,x],a_i=max(a_i,y)\)
2 x y
,从下标 \(x\) 开始,从左往右访问 \(a\),若 \(a_i≤y\),则 \(ans++,y=y-a_i\)
对每次操作 \(2\),输出 \(ans\)。
题解
是一道练习线段树二分的好题。
操作 \(1\) 很容易,只需要二分出小于 \(y\) 的第一个位置,区间覆盖即可。
对于操作 \(2\),易证计入答案的位置必然是不多于 \(log_2 y\) 段区间。而对于一段区间,其长度必然是使得和小于等于 \(y\) 的极大值。于是可以二分。
时间复杂度 \(O(n log y log n)\)。
操作二可以用一种比理论更加方便的操作方法,即在线段树二分的基础上,对 \(y\) 进行修改与询问。详见代码。
int query(int x,int &y,int p=1,int l=1,int r=n) {
if(r<x||y<mn[p]) return 0;
if(l>=x&&y>=sum[p]) {y-=sum[p]; return r-l+1;}
int mid=l+r>>1; pushdown(p,l,r);
return query(x,y,p<<1,l,mid)+query(x,y,p<<1|1,mid+1,r);
}