bzoj-3110-K大数查询(动态第K大 树套树)

题目
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)]);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42576687/article/details/89880437
今日推荐