CF出好题!!!!
修改:
这道题的区间修改有些复杂
但是题目中有一句话:给定一个大小为 n 的非升序列 a。
因此要修改某个区间,一定是从区间某个位置之后到区间结束为止,在这个新区间进行修改。
这时就可以进行二分了,查询某个单点,是否大于y,然后就可以修改了
查询:
第一眼看过去这个查询好坑啊
关键是它还可以跳过某个节点
这里可以简化一下问题,查询之前,可以加上[1,x]的值,使得查询区间变成[1,n]简化了问题
除了维护区间和之外,还要维护区间最小值,一般查询是否可以经过某一区间,如此时的val大于这一最小值即可进入区间
所以要写两个查询函数,第一个是查询区间和,第二个是查询区间长度
int ask(int p,int l,int r)
{
if(l<=e[p].l&&e[p].r<=r) return e[p].sum;
spread(p);
int ans=0;
int mid=(e[p].l+e[p].r)>>1;
if(l<=mid) ans+=ask(ls(p),l,r);
if(mid<r) ans+=ask(rs(p),l,r);
return ans;
}
int query(int p,int &val)
{
if(val>=e[p].sum)
{
val-=e[p].sum;
return e[p].r-e[p].l+1;
}
if(e[p].l==e[p].r) return 0;
spread(p);
int ans=0;
int mid=(e[p].l+e[p].r)>>1;
if(e[ls(p)].mi<=val) ans+=query(ls(p),val);
if(e[rs(p)].mi<=val) ans+=query(rs(p),val);
return ans;
}
除此之外,感觉这道题的懒标记下传也有点意思,就不说了
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define int long long
//#define double long double
//#define double long long
#define re int
//#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define mk make_pair
#define P pair < int , int >
using namespace std;
const int mod=1e9+7;
//const int inf=1e18;
const int M=1e8;
const int N=4e6+5;//??????.???? 4e8
struct node
{
int l,r,sum,add,mi;
}e[N];
int n,m;
void pushup(int p)
{
e[p].sum=e[ls(p)].sum+e[rs(p)].sum;
e[p].mi=min(e[ls(p)].mi,e[rs(p)].mi);
}
void spread(int p)
{
if(e[p].add)
{
e[ls(p)].sum=(e[ls(p)].r-e[ls(p)].l+1)*e[p].add;
e[rs(p)].sum=(e[rs(p)].r-e[rs(p)].l+1)*e[p].add;
e[ls(p)].add=e[p].add;
e[rs(p)].add=e[p].add;
e[ls(p)].mi=e[p].add;
e[rs(p)].mi=e[p].add;
e[p].add=0;
}
}
void bulid(int p,int l,int r)
{
e[p].l=l,e[p].r=r;
if(l==r)
{
scanf("%lld",&e[p].sum);
e[p].mi=e[p].sum;
return;
}
int mid=(l+r)>>1;
bulid(ls(p),l,mid);bulid(rs(p),mid+1,r);
pushup(p);
}
void change(int p,int l,int r,int d)
{
if(l<=e[p].l&&e[p].r<=r)
{
e[p].sum=(e[p].r-e[p].l+1)*d;
e[p].add=d;
return;
}
spread(p);
int mid=(e[p].l+e[p].r)>>1;
if(l<=mid) change(ls(p),l,r,d);
if(mid<r) change(rs(p),l,r,d);
pushup(p);
}
int ask(int p,int l,int r)
{
if(l<=e[p].l&&e[p].r<=r) return e[p].sum;
spread(p);
int ans=0;
int mid=(e[p].l+e[p].r)>>1;
if(l<=mid) ans+=ask(ls(p),l,r);
if(mid<r) ans+=ask(rs(p),l,r);
return ans;
}
int query(int p,int &val)
{
if(val>=e[p].sum)
{
val-=e[p].sum;
return e[p].r-e[p].l+1;
}
if(e[p].l==e[p].r) return 0;
spread(p);
int ans=0;
int mid=(e[p].l+e[p].r)>>1;
if(e[ls(p)].mi<=val) ans+=query(ls(p),val);
if(e[rs(p)].mi<=val) ans+=query(rs(p),val);
return ans;
}
void solve()
{
cin>>n>>m;
bulid(1,1,n);
while(m--)
{
int op,x,y;
scanf("%lld%lld%lld",&op,&x,&y);
if(op==1)
{
int l=1,r=x,flag=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(ask(1,mid,mid)<y) r=mid-1,flag=mid;
else l=mid+1;
}
if(flag!=-1) change(1,flag,x,y);
}
else
{
if(x>1) y+=ask(1,1,x-1);
printf("%lld\n",query(1,y)-(x-1));
}
}
}
signed main()
{
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
solve();
// puts("");
}
return 0;
}
/*
*/