zoukankan      html  css  js  c++  java
  • bzoj3110[Zjoi2013]K大数查询 树套树

    3110: [Zjoi2013]K大数查询

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 9905  Solved: 2945
    [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

     

    第一次接触树套树
    树套树就是把外层树的每个节点重新开一个树,由于空间要求太大,要动态开点
    对于此题来说,外层权值线段树,内层区间线段树
    查询时,在权值树上向右儿子找在[l,r]的个数,如果不够就要向左走,否则向右
    bzoj数据有负数,注意离散和long long问题

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    #define N 50050
    #define M N<<8
    using namespace std;
    int n,m,tot,cnt,str[N],rt[N<<2],ls[M],rs[M],lz[M];ll sum[M];
    struct ask{int op,a,b,c;}q[N];
    void pushdown(int u,int l,int r){
        if(!lz[u])return;
        int mid=l+r>>1,x=lz[u];
        if(!ls[u])ls[u]=++cnt;
        if(!rs[u])rs[u]=++cnt;
        sum[ls[u]]+=x*(mid-l+1);
        sum[rs[u]]+=x*(r-mid);
        lz[ls[u]]+=x;lz[rs[u]]+=x;
        lz[u]=0;
    }
    void update(int &u,int L,int R,int l,int r){
        if(!u)u=++cnt;
        if(l<=L&&R<=r){
            sum[u]+=R-L+1;
            lz[u]++;
            return;
        }pushdown(u,L,R);
        int mid=L+R>>1;
        if(l<=mid)update(ls[u],L,mid,l,r);
        if(r>mid)update(rs[u],mid+1,R,l,r);
        sum[u]=sum[ls[u]]+sum[rs[u]];
    }
    void add(int u,int L,int R,int l,int r,int p){
        update(rt[u],1,n,l,r);
        if(L==R)return;
        int mid=L+R>>1;
        if(p<=mid)add(u<<1,L,mid,l,r,p);
        else add(u<<1|1,mid+1,R,l,r,p);
    }
    ll query(int u,int L,int R,int l,int r){
        if(l<=L&&R<=r)return sum[u];
        pushdown(u,L,R);
        int mid=L+R>>1;ll tt=0;
        if(l<=mid)tt+=query(ls[u],L,mid,l,r);
        if(r>mid)tt+=query(rs[u],mid+1,R,l,r);
        return tt;
    }
    int calc(int u,int L,int R,int l,int r,ll k){
        if(L==R)return L;
        int mid=L+R>>1;
        ll tmp=query(rt[u<<1|1],1,n,l,r);
        if(tmp>=k)return calc(u<<1|1,mid+1,R,l,r,k);
        return calc(u<<1,L,mid,l,r,k-tmp);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&q[i].op,&q[i].a,&q[i].b,&q[i].c);
            if(q[i].op==1)str[++tot]=q[i].c;
        }
        sort(str+1,str+1+tot);
        int len=unique(str+1,str+1+tot)-str-1;
        for(int i=1;i<=m;i++){
            int op=q[i].op,a=q[i].a,b=q[i].b,c=q[i].c;
            if(op==1)c=lower_bound(str+1,str+1+len,c)-str;
            if(op==1)add(1,1,len,a,b,c);
            else printf("%d
    ",str[calc(1,1,len,a,b,c)]);
        }
        return 0;
    }
  • 相关阅读:
    请简单说一下你了解的端口及对应的服务?
    地址解析协议ARP和逆地址解析协议RARP
    IP地址分类
    OSI分层和五层协议
    对象如何晋升到老年代?
    JVM 垃圾回收机制,何时触发 MinorGC 等操作
    什么是引用?
    类加载机制
    Solaris10怎么创建flash archive
    RPC: program not registered (ZT)
  • 原文地址:https://www.cnblogs.com/wsy01/p/8071968.html
Copyright © 2011-2022 走看看