题解:整体二分
以时间为关键字进行整体二分
用线段树维护区间和
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;
}