题解:整体二分
以时间为关键字进行整体二分
用线段树维护区间和
Woc这题居然爆int,以后注意爆int的可能
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=200009; const int inf=1000000000; typedef long long Lint; int n,m; int ans[maxn]; int isquery[maxn]; struct SegmentTree{ int l,r,tag,cle; Lint sum; }tree[maxn<<1]; void pushup(int now){ tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; } void pushdown(int now){ if(tree[now].cle){ tree[now<<1].sum=tree[now<<1].tag=0; tree[now<<1|1].sum=tree[now<<1|1].tag=0; tree[now<<1].cle=tree[now<<1|1].cle=1; tree[now].cle=0; } if(tree[now].tag){ tree[now<<1].tag+=tree[now].tag; tree[now<<1|1].tag+=tree[now].tag; tree[now<<1].sum+=1LL*tree[now].tag*(tree[now<<1].r-tree[now<<1].l+1); tree[now<<1|1].sum+=1LL*tree[now].tag*(tree[now<<1|1].r-tree[now<<1|1].l+1); tree[now].tag=0; } } void BuildTree(int now,int l,int r){ tree[now].l=l;tree[now].r=r; tree[now].tag=tree[now].sum=tree[now].cle=0; if(l==r)return; int mid=(l+r)>>1; BuildTree(now<<1,l,mid); BuildTree(now<<1|1,mid+1,r); } void Updatasec(int now,int ll,int rr,int x){ if(tree[now].l>=ll&&tree[now].r<=rr){ tree[now].tag+=x; tree[now].sum+=1LL*x*(tree[now].r-tree[now].l+1); return; } pushdown(now); int mid=(tree[now].l+tree[now].r)>>1; if(ll<=mid)Updatasec(now<<1,ll,rr,x); if(rr>mid)Updatasec(now<<1|1,ll,rr,x); pushup(now); } Lint Querysum(int now,int ll,int rr){ if(tree[now].l>=ll&&tree[now].r<=rr){ return tree[now].sum; } pushdown(now); int mid=(tree[now].l+tree[now].r)>>1; Lint ret=0; if(ll<=mid)ret+=Querysum(now<<1,ll,rr); if(rr>mid)ret+=Querysum(now<<1|1,ll,rr); return ret; } struct OPTS{ int opty,l,r,z,t; }opt[maxn],q[maxn]; int cmpt(const OPTS &rhs1,const OPTS &rhs2){ return rhs1.t<rhs2.t; } void ClearTree(){ tree[1].cle=1; tree[1].sum=tree[1].tag=0; } void Div(int l,int r,int Lb,int Rb){ // cout<<l<<‘ ‘<<r<<‘ ‘<<Lb<<‘ ‘<<Rb<<endl; if(l>r)return; if(Lb==Rb){ for(int i=l;i<=r;++i){ ans[opt[i].t]=Lb; } return; } int midans=(Lb+Rb)>>1; ClearTree(); int t1=l,t2=r; for(int i=l;i<=r;++i){ if(opt[i].opty==1){ if(opt[i].z>midans){ Updatasec(1,opt[i].l,opt[i].r,1); q[t2--]=opt[i]; }else{ q[t1++]=opt[i]; } }else{ Lint tmp=Querysum(1,opt[i].l,opt[i].r); if(tmp>=opt[i].z){ q[t2--]=opt[i]; }else{ opt[i].z-=tmp; q[t1++]=opt[i]; } } } for(int i=t1;i<=(r+t1)/2;++i){ swap(q[i],q[r-i+t1]); } for(int i=l;i<=r;++i)opt[i]=q[i]; Div(l,t1-1,Lb,midans); Div(t1,r,midans+1,Rb); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ scanf("%d%d%d%d",&opt[i].opty,&opt[i].l,&opt[i].r,&opt[i].z); opt[i].t=i; if(opt[i].opty==2)isquery[i]=1; } BuildTree(1,1,n); Div(1,m,-n,n); for(int i=1;i<=m;++i){ if(isquery[i])printf("%d\n",ans[i]); } return 0; }