zoukankan      html  css  js  c++  java
  • 主席树

    模板

    P3834 【模板】可持久化线段树 2(主席树) 区间求第 (k)

    模板代码
    #include<bits/stdc++.h>
    using namespace std;
    #define Maxn 200005
    typedef long long ll;
    inline int rd()
    {
    	 int x=0;
         char ch,t=0;
         while(!isdigit(ch = getchar())) t|=ch=='-';
         while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
         return x=t?-x:x;
    }
    /*
    len: 数组长度
    cnt: 数据范围 
    */
    int len,n,m,used;
    int root[Maxn],a[Maxn],True_val[Maxn];
    struct Li
    {
    	 int val,num;
    }LI[Maxn];
    bool cmp(Li x,Li y) { return x.val<y.val; }
    struct Tree
    {
    	 int ls,rs,sum;
    }tree[Maxn<<5];
    void pushup(int p)
    {
    	 tree[p].sum=tree[tree[p].ls].sum+tree[tree[p].rs].sum;
    }
    void build(int p,int nl,int nr)
    {
    	 if(nl==nr) return;
    	 int mid=(nl+nr)>>1;
    	 if(mid>=nl) tree[p].ls=++used,build(tree[p].ls,nl,mid);
    	 if(mid<nr) tree[p].rs=++used,build(tree[p].rs,mid+1,nr);
    }
    void add(int p1,int p2,int nl,int nr,int pos,int k)
    {
    	 if(nl==nr) { tree[p2].sum=tree[p1].sum+k; return; }
    	 int mid=(nl+nr)>>1;
    	 tree[p2]=tree[p1];
    	 if(pos<=mid) tree[p2].ls=++used,add(tree[p1].ls,tree[p2].ls,nl,mid,pos,k);
    	 else tree[p2].rs=++used,add(tree[p1].rs,tree[p2].rs,mid+1,nr,pos,k);
    	 pushup(p2);
    }
    int query(int p1,int p2,int nl,int nr,int rank)
    {
    	 if(nl==nr) return nl;
    	 int sumls=tree[tree[p2].ls].sum-tree[tree[p1].ls].sum,mid=(nl+nr)>>1;
    	 if(rank<=sumls) return query(tree[p1].ls,tree[p2].ls,nl,mid,rank);
    	 else return query(tree[p1].rs,tree[p2].rs,mid+1,nr,rank-sumls);
    }
    int main()
    {
         //freopen(".in","r",stdin);
         //freopen(".out","w",stdout);
    	 len=rd(),m=rd();
    	 for(int i=1;i<=len;i++) LI[i].val=rd(),LI[i].num=i;
    	 sort(LI+1,LI+len+1,cmp),LI[0].val=-1;
    	 for(int i=1;i<=len;i++)
    	 {
    	 	 if(LI[i].val!=LI[i-1].val) n++;
    	 	 a[LI[i].num]=n;
    	 	 True_val[n]=LI[i].val;
    	 }
    	 for(int i=0;i<=len;i++) root[i]=++used;
    	 build(root[0],1,n);
    	 for(int i=1;i<=len;i++) add(root[i-1],root[i],1,n,a[i],1);
    	 for(int i=1,l,r,k;i<=m;i++)
    	 {
    	 	 l=rd(),r=rd(),k=rd();
    	 	 printf("%d
    ",True_val[query(root[l-1],root[r],1,n,k)]);
    	 }
         //fclose(stdin);
         //fclose(stdout);
         return 0;
    }
    

    例题

    P3899 [湖南集训]更为厉害

    主要实现内容:给定一棵树,每次询问求出 (u) 的子树内,与 (u) 距离不超过 (k) 的所有节点的点权之和。

    可以考虑以 (dfn) 序列作为 (root[]) ,每一个节点开一棵主席树。

    修改时以每个点的深度为下标,附上点权。

    这样就可以快速查询一颗子树(一段区间),并查询制指定深度的点权之和。

  • 相关阅读:
    C# 获取文件的修改时间、访问时间、创建时间
    Nhibernate Or多条件查询
    C# 将GridView当前页数据导成Execl
    C# 清空文件夹
    TreeView默认收缩
    JS控制控件的隐藏显示
    div置顶,不随滚动条滚动而滚动
    js 父窗体与子窗体的调用
    树形菜单的绑定以及链接
    2010.10.16 OA项目组一周报告 CQ
  • 原文地址:https://www.cnblogs.com/EricQian/p/15067113.html
Copyright © 2011-2022 走看看