传送门biu~
整体二分。我选择把数据用树状数组维护,树状数组可以支持区间修改区间查询。
你们可能永远不会知道一道题没开long long要调多久QAQ
#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;
#define int long long
struct data{
int opt,x,y,c;
}a[50005];
int n,m,tim;
int ans[50005];
int p[50005],tmp[2][50005];
int tree[2][50005],t[2][50005];
inline void add(int opt,int x,int num){
while(x<=n){
if(t[opt][x]!=tim) tree[opt][x]=0;
t[opt][x]=tim;
tree[opt][x]+=num;
x+=lowbit(x);
}
}
inline void add(int l,int r){
add(0,l,1);add(0,r+1,-1);
add(1,l,l);add(1,r+1,-(r+1));
}
inline int search(int opt,int x){
int re=0;
while(x){
if(t[opt][x]!=tim) tree[opt][x]=0;
t[opt][x]=tim;
re+=tree[opt][x];
x-=lowbit(x);
}
return re;
}
inline int search(int x){
return (x+1)*search(0,x)-search(1,x);
}
void binary_search(int L,int R,int l,int r){
if(L>R || l>r) return;
++tim;
int mid=l+r>>1;
if(l==r){
for(int i=L;i<=R;++i){
if(a[p[i]].opt==2) ans[p[i]]=mid;
}
return;
}
tmp[0][0]=tmp[1][0]=0;
for(int i=L;i<=R;++i){
int x=p[i];
if(a[x].opt==1){
if(a[x].c<=mid) tmp[0][++tmp[0][0]]=x;
else{
tmp[1][++tmp[1][0]]=x;
add(a[x].x,a[x].y);
}
}
else{
int tot=search(a[x].y)-search(a[x].x-1);
if(tot<a[x].c){
a[x].c-=tot;
tmp[0][++tmp[0][0]]=x;
}
else tmp[1][++tmp[1][0]]=x;
}
}
int rL=L+tmp[0][0];
memcpy(p+L,tmp[0]+1,sizeof(p[0])*tmp[0][0]);
memcpy(p+rL,tmp[1]+1,sizeof(p[0])*tmp[1][0]);
binary_search(L,rL-1,l,mid);
binary_search(rL,R,mid+1,r);
}
#undef int
int main(){
#define int long long
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;++i) scanf("%lld%lld%lld%lld",&a[i].opt,&a[i].x,&a[i].y,&a[i].c),p[i]=i;
binary_search(1,m,1,n);
for(int i=1;i<=m;++i){
if(a[i].opt==2) printf("%lld\n",ans[i]);
}
return 0;
}