Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
Input
第一行N,M
接下来M行,每行形如1 a b c或2 a b c
Output
输出每个询问的结果
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
1
2
1
2
1
HINT
【样例说明】
第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1
的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是
1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3
大的数是 1 。
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中c<=Maxlongint
正解:整体二分
一道整体二分板子题。。这回竟然调线段树调了好久。。
先以时间为序,二分答案,大于mid的修改就更新,对于每个询问,如果这段区间大于mid的数>=k,说明当前答案小了,放到右半区间,否则放到左半区间。
//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define ls (x<<1)
#define rs (x<<1|1)
#define il inline
#define RG register
#define uint long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
using namespace std;
struct node{ uint t,l,r,k,id; }q[50010],qu1[50010],qu2[50010];
uint sum[500010],lazy[500010],ans[50010],n,m,cnt;
il uint gi(){
RG uint x=0,q=0; RG char ch=getchar();
while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=1,ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q ? -x : x;
}
il void down(RG uint x,RG uint l,RG uint r){
RG uint mid=(l+r)>>1;
sum[ls]+=(mid-l+1)*lazy[x],sum[rs]+=(r-mid)*lazy[x];
lazy[ls]+=lazy[x],lazy[rs]+=lazy[x],lazy[x]=0;
return;
}
il void update(RG uint x,RG uint l,RG uint r,RG uint xl,RG uint xr,RG uint v){
if (xl<=l && r<=xr){ sum[x]+=(r-l+1)*v,lazy[x]+=v; return; }
if (lazy[x]) down(x,l,r); RG uint mid=(l+r)>>1;
if (xr<=mid) update(ls,l,mid,xl,xr,v);
else if (xl>mid) update(rs,mid+1,r,xl,xr,v);
else update(ls,l,mid,xl,mid,v),update(rs,mid+1,r,mid+1,xr,v);
sum[x]=sum[ls]+sum[rs]; return;
}
il uint query(RG uint x,RG uint l,RG uint r,RG uint xl,RG uint xr){
if (xl<=l && r<=xr) return sum[x];
if (lazy[x]) down(x,l,r); RG uint mid=(l+r)>>1,res=0;
if (xr<=mid) res=query(ls,l,mid,xl,xr);
else if (xl>mid) res=query(rs,mid+1,r,xl,xr);
else res=query(ls,l,mid,xl,mid)+query(rs,mid+1,r,mid+1,xr);
return res;
}
il void solve(RG uint l,RG uint r,RG uint L,RG uint R){
if (l>r) return; if (L==R){ for (RG uint i=l;i<=r;++i) if (q[i].t==2) ans[q[i].id]=L; return; }
RG uint mid=(L+R)>>1,t1=0,t2=0;
for (RG uint i=l;i<=r;++i)
if (q[i].t==1){ if (q[i].k>mid) update(1,1,n,q[i].l,q[i].r,1),qu2[++t2]=q[i]; else qu1[++t1]=q[i]; }
else{
RG uint res=query(1,1,n,q[i].l,q[i].r);
if (res>=q[i].k) qu2[++t2]=q[i]; else q[i].k-=res,qu1[++t1]=q[i]; }
for (RG uint i=l;i<=r;++i) if (q[i].t==1 && q[i].k>mid) update(1,1,n,q[i].l,q[i].r,-1);
for (RG uint i=l,j=1;j<=t1;++i,++j) q[i]=qu1[j]; for (RG uint i=l+t1,j=1;j<=t2;++i,++j) q[i]=qu2[j];
solve(l,l+t1-1,L,mid),solve(l+t1,r,mid+1,R); return;
}
il void work(){
n=gi(),m=gi();for (RG uint i=1;i<=m;++i){ q[i].t=gi(),q[i].l=gi(),q[i].r=gi(),q[i].k=gi();if (q[i].t==2) q[i].id=++cnt; }
solve(1,m,1,n); for (RG uint i=1;i<=cnt;++i) printf("%lld
",ans[i]); return;
}
int main(){
File("bzoj3110");
work();
return 0;
}