• BZOJ 3110: [Zjoi2013]K大数查询 [树套树]


    3110: [Zjoi2013]K大数查询

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 6050  Solved: 2007
    [Submit][Status][Discuss]

    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

    Sample Output

    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


    本题做法好多啊,人太弱先写权值线段树套区间线段树吧

    蒟蒻无脑总结:树套树是一种二维数据结构,用来解决二维的信息修改和询问

    本题两个信息,一段区间中保存数,求第k大

    显然用一个区间数据结构一个可求排名的数据结构,可以用权值线段树和区间线段树

    区间线段树在外层,维护增加数的信息好难啊

    权值线段树在外层,每个节点放一颗区间线段树维护这个节点权值在区间中出现次数

    修改...修改就行了啊

    查询,在权值线段树上二分答案,只不过用的是[a,b]中的出现次数

    复杂度nlog^2n

    参考别人写的,好诡异啊,明明有范围那么大还有负数,不离散化也能A

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define m ((l+r)>>1)
    #define lc t[o].l
    #define rc t[o].r
    #define lson t[o].l,l,m
    #define rson t[o].r,m+1,r
    const int N=5e4+5;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    
    int n,Q,op,ql,qr,v;
    struct node{
        int l,r;
        ll sum,tag;
    }t[N*300];
    int sz;
    inline void merge(int o){
        t[o].sum=t[lc].sum+t[rc].sum;
    }
    inline void paint(int &o,int l,int r,ll d){
        if(!o) o=++sz;
        t[o].sum+=(ll)(r-l+1)*d;
        t[o].tag+=d; 
    }
    inline void pushDown(int o,int l,int r){
        if(t[o].tag){
            paint(lson,t[o].tag);
            paint(rson,t[o].tag);
            t[o].tag=0;
        }
    }
    void add(int &o,int l,int r,int ql,int qr,int d){
        if(!o) o=++sz;
        if(ql<=l&&r<=qr) paint(o,l,r,d);
        else{
            pushDown(o,l,r);
            if(ql<=m) add(lson,ql,qr,d);
            if(m<qr) add(rson,ql,qr,d);
            merge(o);
        }
    }
    ll query(int o,int l,int r,int ql,int qr){
        if(!o) return 0;
        if(ql<=l&&r<=qr) return t[o].sum;
        else{
            pushDown(o,l,r);
            ll ans=0;
            if(ql<=m) ans+=query(lson,ql,qr);
            if(m<qr) ans+=query(rson,ql,qr);
            return ans;
        }
    }
    
    int rt[N<<2];
    void add2(int o,int l,int r,int ql,int qr,int v){
        add(rt[o],1,n,ql,qr,1);
        if(l==r) return;
        if(v<=m) add2(o<<1,l,m,ql,qr,v);
        else add2(o<<1|1,m+1,r,ql,qr,v);
    }
    ll query2(int o,int l,int r,int ql,int qr,int k){
        if(l==r) return l;
        ll rsize=query(rt[o<<1|1],1,n,ql,qr);
        if(rsize>=k) return query2(o<<1|1,m+1,r,ql,qr,k);
        else return query2(o<<1,l,m,ql,qr,k-rsize);
    }
    int main(){
        //freopen("in.txt","r",stdin);
        n=read();Q=read();
        while(Q--){
            op=read();ql=read();qr=read();v=read();
            if(op==1) add2(1,1,n,ql,qr,v);
            else printf("%lld
    ",query2(1,1,n,ql,qr,v));
        }
    }
  • 相关阅读:
    一文详解云上自动化部署集群管理工具 Nebula Operator
    手把手教你从数据预处理开始体验图数据库
    图查询语言的历史回顾短文
    集群通信:从心跳说起
    @Constraint 自定义注解校验手机号
    【工具】maven插件自动生成mapper文件
    【工具】方法日志打印+任务切片
    简单梳理下 Vue3 的新特性
    团队与领导力健康检查 | 体检表
    详细介绍Scrum Master八大职责(Scrum Master能力说明)
  • 原文地址:https://www.cnblogs.com/candy99/p/6246513.html
Copyright © 2020-2023  润新知