树套树-权值线段树套区间线段树

树套树留坑

线段树套线段树:

K大数查询

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include<bitset>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
const int N=50000,M=50000*16*16;
int n,m;
int tot=0,rt[N*4+10],tl[M+10],tr[M+10],add[M+10];
ll sum[M+10];
int cnt=0;
struct node
{
    int val,id;
}b[N+10];
struct Q
{
    int op,l,r;ll k;
}q[N+10];
template<typename T> inline void read(T &x)
{
    x=0;int f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    x=x*f;
}
bool cmp(node a,node b)
{
    return a.val<b.val;
}
void ask_add(int &k,int l,int r,int ql,int qr)
{
    if(!k) k=++tot;
    sum[k]+=min(r,qr)-max(l,ql)+1;
    if(ql<=l&&r<=qr)
    {
        add[k]++;
        return;
    }
    int mid=(l+r)>>1;
    if(ql<=mid) ask_add(tl[k],l,mid,ql,qr);
    if(qr>=mid+1) ask_add(tr[k],mid+1,r,ql,qr);
}
ll ask_sum(int &k,int l,int r,int ql,int qr,int d=0)
{
    if(!k) return d*(min(r,qr)-max(l,ql)+1);
    if(ql<=l&&r<=qr) return sum[k]+d*(r-l+1);
    ll val=0;
    int mid=(l+r)>>1;
    if(ql<=mid) val+=ask_sum(tl[k],l,mid,ql,qr,d+add[k]);
    if(qr>=mid+1) val+=ask_sum(tr[k],mid+1,r,ql,qr,d+add[k]);
    return val;
}
void insert(int k,int l,int r,int ql,int qr,int d)
{
    ask_add(rt[k],1,n,ql,qr);
    if(l==r) return;
    int mid=(l+r)>>1;
    if(d<=mid) insert(k<<1,l,mid,ql,qr,d);
    else insert(k<<1|1,mid+1,r,ql,qr,d);
}
int kth(int k,int l,int r,int ql,int qr,ll d)
{
    if(l==r) return l;
    int mid=(l+r)>>1;
    ll rcnt=ask_sum(rt[k<<1|1],1,n,ql,qr);
    if(rcnt<d) return kth(k<<1,l,mid,ql,qr,d-rcnt);
    else return kth(k<<1|1,mid+1,r,ql,qr,d);
}
inline void init()
{
    sort(b+1,b+cnt+1,cmp);
    int i=1,j=1;
    while(j<=cnt)
    {
        b[i]=b[j];
        while(b[i].val==b[j].val&&j<=cnt) q[b[j++].id].k=i;
        ++i;
    }
    cnt=i-1;
}
int main()
{
    read(n),read(m);
    rep(i,1,m)
    {
        read(q[i].op),read(q[i].l),read(q[i].r),read(q[i].k);
        if(q[i].op==1) b[++cnt].val=q[i].k,b[cnt].id=i;
    }
    init();
    rep(i,1,m)
    {
        if(q[i].op==1) insert(1,1,cnt,q[i].l,q[i].r,q[i].k);
        if(q[i].op==2) printf("%d\n",b[kth(1,1,cnt,q[i].l,q[i].r,q[i].k)].val);
    }
    return 0;
}

转载于:https://www.cnblogs.com/MYsBlogs/p/11423739.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值