zoukankan      html  css  js  c++  java
  • 【Luogu】P3332K大数查询(树套树)

      题目链接

      这题我费尽心思不用标记永久化终于卡过去了qwq

      权值线段树下面套一个区间线段树。然后乱搞搞即可。

      

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #define maxn 100050
    #define mid ((l+r)>>1)
    #define left (root<<1)
    #define right (root<<1|1)
    #define check(o)    if(o==0)    o=++segtot;
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    long long tree[maxn*200];int segtot;
    int segrt[maxn*200];
    int segls[maxn*200];
    int segrs[maxn*200];
    int tag[maxn*200];
    int rt[maxn*10];
    int q[maxn];
    int n,m,cnt,size;
    
    
    void pushdown(int &root,int m){
        check(root);
        if(tag[root]==0)    return;
        check(segls[root]);
        check(segrs[root]);
        int le=segls[root],ri=segrs[root];
        tag[le]+=tag[root];    tag[ri]+=tag[root];
        tree[le]+=tag[root]*(m-(m>>1));
        tree[ri]+=tag[root]*(m>>1);
        tag[root]=0;
    }
    
    void segup(int from,int to,int l,int r,int &root){
        check(root);
        if(from<=l&&to>=r){
            tree[root]+=(r-l+1);
            tag[root]++;
            return;
        }
        pushdown(root,r-l+1);
        if(from<=mid){
            check(segls[root]);
            segup(from,to,l,mid,segls[root]);
        }
        if(to>mid){
            check(segrs[root]);
            segup(from,to,mid+1,r,segrs[root]);
        }
        tree[root]=tree[segls[root]]+tree[segrs[root]];
    }
    
    long long segquery(int from,int to,int l,int r,int &root){
        check(root);
        if(from<=l&&to>=r)    return tree[root];
        pushdown(root,r-l+1);
        long long ans=0;
        if(from<=mid){
            check(segls[root]);
            ans+=segquery(from,to,l,mid,segls[root]);
        }
        if(to>mid){
            check(segrs[root]);
            ans+=segquery(from,to,mid+1,r,segrs[root]);
        }
        return ans;
    }
    
    void add(int o,int from,int to,int l,int r,int p){
        segup(from,to,1,n,segrt[o]);
        if(l==r)    return;
        if(p<=mid)    add(o<<1,from,to,l,mid,p);
        else    add(o<<1|1,from,to,mid+1,r,p);
    }
    
    long long query(int o,int from,int to,long long l,long long r,long long e){
        if(l==r)    return l;
        long long ans=segquery(from,to,1,n,segrt[o<<1|1]);
        if(ans>=e)    return query(o<<1|1,from,to,mid+1,r,e);
        else        return query(o<<1,from,to,l,mid,e-ans);
    }
    
    struct Que{
        long long opt,a,b,c;
    }que[maxn];
    
    int main(){
        n=read(),m=read();
        for(int i=1;i<=m;++i){
            que[i]=(Que){read(),read(),read(),read()};
            if(que[i].opt==1)    q[++cnt]=que[i].c;
        }
        sort(q+1,q+cnt+1);
        size=unique(q+1,q+cnt+1)-q-1;
        for(int i=1;i<=m;++i){
            if(que[i].opt!=1)    continue;
            que[i].c=lower_bound(q+1,q+size+1,que[i].c)-q;
        }
        for(int i=1;i<=m;++i){
            long long  opt=que[i].opt,a=que[i].a,b=que[i].b,c=que[i].c;
            if(opt==1)    add(1,a,b,1,size,c);
            else        printf("%lld
    ",q[query(1,a,b,1,size,c)]);
        }
        return 0;
    }
  • 相关阅读:
    java下载url图片链接
    mysql 设计索引的原则
    169. 多数元素
    263. 丑数
    markdown 语法笔记
    70.爬楼梯
    540. 有序数组中的单一元素
    88. 合并两个有序数组
    面试题57
    152. 乘积最大子序列
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8312758.html
Copyright © 2011-2022 走看看