zoukankan      html  css  js  c++  java
  • 【笔记】【数据结构】【树】主席树

    技巧一:离散去重

    for(int i=1;i<=n;i++) scanf("%d",&a[i] ),b[i]=a[i];
        sort(b+1,b+n+1);
        int nn=unique(b+1,b+n+1)-b-1;//假设有x个数,那么nn指针会停在第x+1个数的位置 ,nn及以后的都是重复的元素for(int i=1;i<=n;i++)
            id[i]=lower_bound(b+1,b+nn+1,a[i])-b;//离散过后的新value

    技巧二:可持久化数据结构

    修改被影响的部分,然后用指针指向新的点,记录新的点,就可以方便查找了

    void updata(int l,int r,int &nw,int pre,int x)
    {
        nw=++cnt;
        t[nw]=t[pre];t[nw].sum ++;
        if(l==r) return ;
        int mid=(l+r)>>1;
        if(mid>=x) updata(l,mid,t[nw].lc ,t[pre].lc ,x);
        else updata(mid+1,r,t[nw].rc ,t[pre].rc ,x);
    }

    技巧三:区间问题一般都可以被拆成a[R]-a[L-1]

    即使每个a有N个分支

    int query(int l,int r,int ll,int rr,int kk)
    {
        if(l==r) return l;
        int s=t[t[rr].lc ].sum -t[t[ll].lc ].sum ;
        int mid=(l+r)>>1;
        if(s>=kk) return query(l,mid,t[ll].lc ,t[rr].lc ,kk);
        else return query(mid+1,r,t[ll].rc ,t[rr].rc ,kk-s);
    }

    最后:主席树模板

    //luogu P3834 
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int n,m;
    const int N=200003;
    int a[N],b[N],id[N];
    
    struct node
    {
        int sum,lc,rc;
    }t[N*40];
    int cnt,rt[N];
    int build(int l,int r)
    {
        int rt=++cnt;
        t[rt].sum =0;
        if(l!=r)
        {
            int mid=(l+r)>>1;
            t[rt].lc =build(l,mid);
            t[rt].rc =build(mid+1,r);
        }
        return rt;
    }
    void updata(int l,int r,int &nw,int pre,int x)
    {
        nw=++cnt;
        t[nw]=t[pre];t[nw].sum ++;
        if(l==r) return ;
        int mid=(l+r)>>1;
        if(mid>=x) updata(l,mid,t[nw].lc ,t[pre].lc ,x);
        else updata(mid+1,r,t[nw].rc ,t[pre].rc ,x);
    }
    
    int query(int l,int r,int ll,int rr,int kk)
    {
        if(l==r) return l;
        int s=t[t[rr].lc ].sum -t[t[ll].lc ].sum ;
        int mid=(l+r)>>1;
        if(s>=kk) return query(l,mid,t[ll].lc ,t[rr].lc ,kk);
        else return query(mid+1,r,t[ll].rc ,t[rr].rc ,kk-s);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i] ),b[i]=a[i];
        sort(b+1,b+n+1);
        int nn=unique(b+1,b+n+1)-b-1;//假设有x个数,那么nn指针会停在第x+1个数的位置 
        //去重,离散
        rt[0]=build(1,nn);
        for(int i=1;i<=n;i++)
        {
            id[i]=lower_bound(b+1,b+nn+1,a[i])-b;
            updata(1,nn,rt[i],rt[i-1],id[i]);//需要a数组的数到序号的离散
        }//离散过后的新value
        int x,y,k;
        while(m--)
        {
            scanf("%d%d%d",&x,&y,&k);
            printf("%d
    ",b[ query(1,nn,rt[x-1],rt[y],k) ]);//需要序号到b数组的离散
        }
        return 0;
    }
  • 相关阅读:
    微服务实战(三):深入微服务架构的进程间通信
    微服务实战(二):使用API Gateway
    微服务实战(一):微服务架构的优势与不足
    函数声明与函数表达式
    CSS样式优先级
    iframe框架及优缺点
    JS事件流模型
    JS事件冒泡及阻止
    浏览器重绘与回流
    浏览器渲染与内核
  • 原文地址:https://www.cnblogs.com/xwww666666/p/11270249.html
Copyright © 2011-2022 走看看