权值线段树+区间线段树
对权值线段树每一个节点开一个区间线段树,动态开点。
#include
#include
#include
#include
#include
#include
using namespace std;
const int N=5e4+10;
struct TREE{
long long sum,f;
int l,r;
}tree[N*400];
struct NODE{
int opt,l,r;
long long c;
}node[N];
int root[N*4];
long long h[N];
int n,m,cnt,tot;
void pushdown(int x,int ll,int rr)
{
if(tree[x].f)
{
if(!tree[x].l) tree[x].l=++tot; //注意这个添点操作!!!
if(!tree[x].r) tree[x].r=++tot;
int l=tree[x].l; int r=tree[x].r;
int mid=(ll+rr)>>1;
tree[l].sum+=tree[x].f*(mid-ll+1); tree[l].f+=tree[x].f; //注意乘以区间长度!!!
tree[r].sum+=tree[x].f*(rr-mid); tree[r].f+=tree[x].f;
tree[x].f=0;
}
}
void insert(int &x,int l,int r,int ll,int rr)
{
if(!x)
x=++tot;
if(ll<=l&&r<=rr)
{
tree[x].sum+=r-l+1; tree[x].f++; //注意加上区间长度!!!
return;
}
int mid=(l+r)>>1;
pushdown(x,l,r); //pushdown !!!
if(ll<=mid) insert(tree[x].l,l,mid,ll,rr);
if(rr>mid) insert(tree[x].r,mid+1,r,ll,rr);
tree[x].sum=tree[tree[x].l].sum+tree[tree[x].r].sum; // pushup!!!
}
void ins(int x,int l,int r,int v,int a,int b)
{
insert(root[x],1,n,a,b); //每经过一个点都要insert!!!
if(l==r) return;
int mid=(l+r)>>1;
if(v>mid) ins(x*2+1,mid+1,r,v,a,b);
else ins(x*2,l,mid,v,a,b);
}
long long query(int x,int l,int r,int ll,int rr,long long v)
{
if(!x) return 0;
if(ll<=l&&r<=rr) return tree[x].sum;
pushdown(x,l,r); //pushdown!!!
int mid=(l+r)>>1;
if(ll>mid) return query(tree[x].r,mid+1,r,ll,rr,v);
if(rr<=mid) return query(tree[x].l,l,mid,ll,rr,v);
return query(tree[x].l,l,mid,ll,rr,v)+query(tree[x].r,mid+1,r,ll,rr,v);
}
long long qry(int x,int l,int r,long long v,int a,int b)
{
if(l==r) return h[l];
int mid=(l+r)>>1;
long long size=query(root[x*2+1],1,n,a,b,v);
if(size<v) return qry(x*2,l,mid,v-size,a,b);
else return qry(x*2+1,mid+1,r,v,a,b);
}
int main()
{
int tcnt=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%lld",&node[i].opt,&node[i].l,&node[i].r,&node[i].c);
if(node[i].opt==1) h[++tcnt]=node[i].c;
}
sort(h+1,h+tcnt+1);
cnt=unique(h+1,h+tcnt+1)-h-1;
for(int i=1;i<=m;i++)
{
if(node[i].opt==1)
{
int c=lower_bound(h+1,h+cnt+1,node[i].c)-h; //传int和传longlong时间差很多
ins(1,1,cnt,c,node[i].l,node[i].r);
}
else
printf("%lld\n",qry(1,1,cnt,node[i].c,node[i].l,node[i].r));
}
return 0;
}
/*
2 7
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
1 1 1 2
2 1 1 3
*/