权值线段树

定义

线段树学习

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

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

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

权值线段树可以解决:

 

实现

 

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\n",rank_of_x(1,N,1,get(w[i])-1,1)+1);
    else if(op[i]==4) printf("%d\n",scatter[rank_is_x(1,N,w[i],1)-1]);
    else if(op[i]==5) printf("%d\n",scatter[rank_is_x(1,N,rank_of_x(1,N,1,get(w[i])-1,1),1)-1]);
    else printf("%d\n",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);
}
posted @ 2019-09-07 23:25  Vivid-BinGo  阅读(153)  评论(0编辑  收藏  举报