zoukankan      html  css  js  c++  java
  • 权值线段树

    定义

    线段树学习

    权值线段树和线段树类似,只是维护的数据不一样而已。权值线段树的叶节点维护的是数据出现的次数。

    为了防止数据过大,一般先离散化数据再使用权值线段树维护。

    主席树的前置技能为权值线段树。

    权值线段树可以解决:

    实现

    P3369 【模板】普通平衡树

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    struct node
    {int L,R,w;}tree[maxn<<2];
    int op[maxn],w[maxn];
    vector<int> scatter;
    void build(int L,int R,int k);
    int get(int x);
    void update(int L,int R,int w,int f,int k);
    int rank_of_x(int L,int R,int l,int r,int k);
    int rank_is_x(int L,int R,int rank,int k);
    int main()
    {
      int i,n,N;
      scanf("%d",&n);
      for(i=1;i<=n;i++)
      {
        scanf("%d%d",&op[i],&w[i]);
        if(op[i]!=4) scatter.push_back(w[i]);
      }
      sort(scatter.begin(),scatter.end());
      scatter.resize(unique(scatter.begin(),scatter.end())-scatter.begin());
      N=scatter.size();build(1,N,1);
      for(i=1;i<=n;i++)
      {
        if(op[i]==1) update(1,N,get(w[i]),1,1);
        else if(op[i]==2) update(1,N,get(w[i]),-1,1);
        else if(op[i]==3) printf("%d
    ",rank_of_x(1,N,1,get(w[i])-1,1)+1);
        else if(op[i]==4) printf("%d
    ",scatter[rank_is_x(1,N,w[i],1)-1]);
        else if(op[i]==5) printf("%d
    ",scatter[rank_is_x(1,N,rank_of_x(1,N,1,get(w[i])-1,1),1)-1]);
        else printf("%d
    ",scatter[rank_is_x(1,N,rank_of_x(1,N,1,get(w[i]),1)+1,1)-1]);
      }
      system("pause");
      return 0;
    }
    void build(int L,int R,int k)
    {
      tree[k].L=L;tree[k].R=R;
      if(L==R)
      {
        tree[k].w=0;
        return ;
      }
      int mid=(L+R)/2;
      build(L,mid,k<<1);
      build(mid+1,R,k<<1|1);
      tree[k].w=tree[k<<1].w+tree[k<<1|1].w;
    }
    int get(int x)
    {return lower_bound(scatter.begin(),scatter.end(),x)-scatter.begin()+1;}
    void update(int L,int R,int w,int f,int k)
    {
      if(L==R)
      {
        tree[k].w+=f;
        return ;
      }
      int mid=(L+R)/2;
      if(w<=mid) update(L,mid,w,f,k<<1);
      else update(mid+1,R,w,f,k<<1|1);
      tree[k].w=tree[k<<1].w+tree[k<<1|1].w;
    }
    int rank_of_x(int L,int R,int l,int r,int k)
    {
      if(l>r) return 0;
      if(L>=l&&R<=r) return tree[k].w;
      int mid=(L+R)/2,ans=0;
      if(l<=mid) ans+=rank_of_x(L,mid,l,r,k<<1);
      if(r>mid) ans+=rank_of_x(mid+1,R,l,r,k<<1|1);
      return ans;
    }
    int rank_is_x(int L,int R,int rank,int k)
    {
      if(L==R) return R;
      int mid=(L+R)/2;
      if(rank<=tree[k<<1].w) return rank_is_x(L,mid,rank,k<<1);
      else return rank_is_x(mid+1,R,rank-tree[k<<1].w,k<<1|1);
    }
  • 相关阅读:
    itoa
    sprintf用法 [转载]
    atoi 与 itoa的实现
    数组排序总结(冒泡,选择,插入,希尔)
    XML入门精解之文件格式定义(DTD)
    malloc()函数的工作机制 结构体的总结
    字符串指针与字符数组(ZT)
    sprintf函数你了解有多深!
    sprintf
    sql ldr 笔记
  • 原文地址:https://www.cnblogs.com/VividBinGo/p/11483841.html
Copyright © 2011-2022 走看看