zoukankan      html  css  js  c++  java
  • zoj

    ZOJ - 2112

    题意:求区间第k小

    思路:带修改区间第k小裸题,无修改的主席树是维护一个前缀线段树,每次更新log个节点,用root 和 ls rs作为每颗前缀线段树的根节点和左右子树的索引(相当于指针),带修改的主席树是也是维护前缀线段树,不过是用树状数组维护,思想和树状数组维护前缀和一样,每次向上更新,向下求和;时间和空间复杂度都是(n+q)*logn*logn;但是zoj卡内存,简直心里阴影,交了近100发才A。。。由于修改比较少内存优化后时间空间复杂度降低到了n*logn+q*logn*logn,但是没有太理解优化的原理,优化操作是先建一颗静态主席树,然后修改操作用另一个S数组索代替root引根节点

    AC代码:

    #include "iostream"
    #include "iomanip"
    #include "string.h"
    #include "stack"
    #include "queue"
    #include "string"
    #include "vector"
    #include "set"
    #include "map"
    #include "algorithm"
    #include "stdio.h"
    #include "math.h"
    #define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
    #define mem(a,x) memset(a,x,sizeof(a))
    #define step(x) fixed<< setprecision(x)<<
    #define mp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define ll long long
    #define endl ("
    ")
    #define ft first
    #define sd second
    #define lrt (rt<<1)
    #define rrt (rt<<1|1)
    using namespace std;
    const ll mod=1e9+7;
    const ll INF = 1e18+1LL;
    const int inf = 1e9+1e8;
    const double PI=acos(-1.0);
    const int N=6e4+100;
    
    int sum[32*N],ls[32*N],rs[32*N],root[N],S[N],cnt;
    int n,m,sz,tk[N],a[N];
    void creat(int &cur, int l, int r){
        cur=++cnt;
        sum[cur]=0;
        if(l==r) return;
        int mid=l+r>>1;
        creat(ls[cur],l,mid);
        creat(rs[cur],mid+1, r);
    }
    
    void update(int &cur, int l, int r, int p, int last, int u){
        cur=++cnt;
        ls[cur]=ls[last];
        rs[cur]=rs[last];
        sum[cur]=sum[last]+u;
        if(l==r) return;
        int mid=l+r>>1;
        if(p<=mid) update(ls[cur], l, mid, p, ls[cur], u);
        else update(rs[cur], mid+1, r, p, rs[cur], u);
    }
    
    int lowbit(int x){
        return x&(-x);
    }
    
    void add(int x, int p, int u){
        while(x<=n){
            update(S[x],1,sz,p,S[x],u);
            x+=lowbit(x);
        }
    }
    
    int query(int l, int r, int L, int R, int k){
        int bit[60010], rtl=root[L], rtr=root[R];
        for(int i=L; i>0; i-=lowbit(i)) bit[i]=S[i];
        for(int i=R; i>0; i-=lowbit(i)) bit[i]=S[i];
        while(l<r){
            int t=sum[ls[rtr]]-sum[ls[rtl]];
            for(int i=R; i>0; i-=lowbit(i)) t+=sum[ls[bit[i]]];
            for(int i=L; i>0; i-=lowbit(i)) t-=sum[ls[bit[i]]];
            int mid=l+r>>1;
            if(t>=k){
                for(int i=L; i>0; i-=lowbit(i)) bit[i]=ls[bit[i]];
                for(int i=R; i>0; i-=lowbit(i)) bit[i]=ls[bit[i]];
                rtl=ls[rtl],rtr=ls[rtr],r=mid;
            }
            else{
                for(int i=L; i>0; i-=lowbit(i)) bit[i]=rs[bit[i]];
                for(int i=R; i>0; i-=lowbit(i)) bit[i]=rs[bit[i]];
                rtl=rs[rtl],rtr=rs[rtr],l=mid+1; k-=t;
            }
        }
        return l;
    }
    
    struct Qu{
        char c[4];
        int l, r, k;
    }q[10005];
    
    void hash_init(){
        sort(tk+1,tk+1+sz);
        sz=unique(tk+1,tk+1+sz)-(tk+1);
    }
    int _hash(int x){
        return lower_bound(tk+1,tk+1+sz,x)-tk;
    }
    int main(){
        int T; scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m); cnt=0,sz=0;//sz表示线段树(主席树)的叶子节点数
            for(int i=1; i<=n; ++i){
                scanf("%d",&a[i]);
                tk[++sz]=a[i];
            }
            for(int i=1; i<=m; ++i){
                scanf("%s",q[i].c);
                if(q[i].c[0]=='Q'){
                    scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
                }
                else{
                    scanf("%d%d",&q[i].l,&q[i].r);
                    tk[++sz]=q[i].r;
                }
            }
            hash_init();
            creat(root[0],1,sz);
            for(int i=1; i<=n; ++i){
                update(root[i],1,sz,_hash(a[i]),root[i-1],1);
            }
            for(int i=1; i<=n; ++i) S[i]=root[0];
            for(int i=1; i<=m; ++i){
                if(q[i].c[0]=='Q'){
                    printf("%d
    ",tk[query(1, sz, q[i].l-1, q[i].r, q[i].k)] );
                }
                else{
                    add(q[i].l, _hash(a[q[i].l]), -1);
                    add(q[i].l, _hash(q[i].r), 1);
                    a[q[i].l]=q[i].r;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    word2vec原理推导与代码分析
    vim 删除
    HanLP 配置与使用
    python import 其他 package的模块
    mysql 修改root密码
    Spring Boot 整合 PageHelper
    MyBatis SQL语句构建器
    webpack4
    MySql DCL数据控制语言(对用户权限的设置)
    MySql DQL数据查询语言
  • 原文地址:https://www.cnblogs.com/max88888888/p/7553596.html
Copyright © 2011-2022 走看看