题目
Elastic Heart
树套树:外层权值线段树,每个权值线段树的节点有一个区间线段树(普通线段树)这里采用动态开点线段树。
每次插入(l,r,val)。就是在以(1,tot)为总区间的权值线段树一直往下二分找到val,包含val的区间都要加入(l,r)。对这些区间线段树意味着区间更新(区间l-r内的值+1)
所以这里还要用到tag懒标记看代码体会吧啊啊啊啊啊啊啊啊啊
//Time:17332 ms Memory:466136 kb
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int N=23000003,M=500003;
struct Query{int opt,l,r;ll val;}q[M];
struct tree
{
int l,r;
tree(){l=r=0;}
}t[N];
ll sum[N],refl[M];
int root[M],tag[N];
int sz,tot,n,m;
void pushdown(int dex,int l,int r)
{
int mid=(l+r)>>1;
int lson=t[dex].l,rson=t[dex].r;
if(!lson) lson=(t[dex].l=++sz);
if(!rson) rson=(t[dex].r=++sz);
tag[lson]+=tag[dex],tag[rson]+=tag[dex];
sum[lson]+=(ll)(mid-l+1)*tag[dex],sum[rson]+=(ll)(r-mid)*tag[dex];
tag[dex]=0;
}
void intspan(int &dex,int cl,int cr,int l,int r)
{
if(!dex)
dex=++sz;
if(tag[dex])
pushdown(dex,l,r);
if(cl<=l&&r<=cr)
{
sum[dex]+=(r-l+1);
tag[dex]++;
return;
}
int mid=(l+r)>>1;
if(cl<=mid)
intspan(t[dex].l,cl,cr,l,mid);
if(cr>mid)
intspan(t[dex].r,cl,cr,mid+1,r);
sum[dex]=sum[t[dex].l]+sum[t[dex].r];
}
void outpoint(int wh,int nl,int nr,int l,int r,int pos)
{
intspan(root[pos],nl,nr,1,n);
if(l==r)
return;
int mid=(l+r)>>1;
if(wh<=mid)
outpoint(wh,nl,nr,l,mid,pos<<1);
else
outpoint(wh,nl,nr,mid+1,r,pos<<1|1);
}
ll intquery(int dex,int cl,int cr,int l,int r)
{
if(cl<=l&&r<=cr)
return sum[dex];
if(tag[dex])
pushdown(dex,l,r);
int mid=(l+r)>>1;
ll ans=0;
if(cl<=mid)
ans+=intquery(t[dex].l,cl,cr,l,mid);
if(cr>mid)
ans+=intquery(t[dex].r,cl,cr,mid+1,r);
return ans;
}
int outquery(int nl,int nr,ll k,int l,int r,int pos)
{
if(l==r)
return l;
int mid=(l+r)>>1;ll tmp=0;
if(root[pos<<1|1])
tmp=intquery(root[pos<<1|1],nl,nr,1,n);
if(tmp>=k)
return outquery(nl,nr,k,mid+1,r,pos<<1|1);
else
return outquery(nl,nr,k-tmp,l,mid,pos<<1);
}
int main()
{
//m(tag,0),m(sum,0),rt=0,tot=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%lld",&q[i].opt,&q[i].l,&q[i].r,&q[i].val);
if(q[i].opt==1)
refl[++tot]=q[i].val;
}
sort(refl+1,refl+tot+1);
tot=unique(refl+1,refl+tot+1)-(refl+1);
for(int i=1;i<=m;i++)
{
if(q[i].opt==1)
{
int dex=lower_bound(refl+1,refl+tot+1,q[i].val)-refl;
outpoint(dex,q[i].l,q[i].r,1,tot,1);
}
else
printf("%lld\n",refl[outquery(q[i].l,q[i].r,q[i].val,1,tot,1)]);
}
}