zoukankan      html  css  js  c++  java
  • BZOJ_3224 Tyvj 1728 普通平衡树 【离散化+权值线段树】

    一 题面

      Tyvj 1728 普通平衡树

    二 分析

      比较明显是可以用平衡二叉搜索树(splay)做的。

      用权值线段树做,前提就是要先离散化,因为权值线段树维护的值域信息。

      板子。

    三 AC代码

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <fstream>
      5 
      6 using namespace std;
      7 #define lson rt<<1
      8 #define rson rt<<1|1
      9 
     10 const int MAXN = 1e5 + 15;
     11 int N, op[MAXN], opx[MAXN];
     12 struct Node
     13 {
     14     int id, x;
     15 }Data[MAXN];
     16 int A[MAXN];
     17 
     18 int segTree[MAXN<<2];
     19 
     20 bool Cmpx(const Node &a, const Node &b)
     21 {
     22     return a.x < b.x;
     23 }
     24 
     25 //p更新的位置,v=-1表示减,v=1表示加
     26 void Update(int p, int v, int rt, int l, int r)
     27 {
     28     segTree[rt] += v;
     29     if(l == r)  return;
     30     int mid = (l+r)>>1;
     31     if(p <= mid) Update(p, v, lson, l, mid);
     32     else    Update(p, v, rson, mid+1, r);
     33 }
     34 //第K小
     35 int Kth(int K, int rt, int l, int r)
     36 {
     37     if(l == r)
     38         return l;
     39     int mid = (l+r)>>1;
     40     if(segTree[lson] >= K)  
     41         return Kth(K, lson, l, mid);
     42     else
     43         return Kth(K-segTree[lson], rson, mid+1, r);
     44 }
     45 //数字v的排名
     46 //统计小于v的数的个数
     47 int Rank(int v, int rt, int l, int r)
     48 {
     49     if(r < v)
     50         return segTree[rt];
     51     int mid = (l+r)>>1, res = 0;
     52     res += Rank(v, lson, l, mid);
     53     //相当于mid+1 < v 那么左边可能还有
     54     if(mid < v-1)
     55         res += Rank(v, rson, mid+1, r);
     56     return res;
     57 }
     58 //找最右边的数
     59 int Findr(int rt, int l, int r)
     60 {
     61     if(l == r)
     62         return l;
     63     int mid = (l+r)>>1;
     64     if(segTree[rson])     return Findr(rson, mid + 1, r);
     65     return Findr(lson, l, mid);
     66 }
     67 //前驱
     68 int Pre(int v, int rt, int l, int r)
     69 {
     70     if(r < v)
     71     {
     72         if(segTree[rt])   return Findr(rt, l, r);
     73         return 0;
     74     }
     75     int mid = (l+r)>>1, res;
     76     //如果v > mid+1那么意味着mid+1或后面的数有可能是前驱
     77     if(mid < v-1 && segTree[rson] && (res=Pre(v,rson,mid+1,r)))
     78         return res;
     79     return Pre(v, lson, l, mid);
     80 }
     81 //找最左边的数
     82 int Findl(int rt, int l, int r)
     83 {
     84     if(l == r)
     85         return l;
     86     int mid = (l+r)>>1;
     87     if(segTree[lson])   return Findl(lson, l, mid);
     88     return Findl(rson, mid+1, r);
     89 }
     90 //后继
     91 int Nex(int v, int rt, int l, int r)
     92 {
     93     if(v < l)
     94     {
     95         if(segTree[rt]) return Findl(rt, l, r);
     96         return 0;
     97     }
     98     int mid = (l+r)>>1, res;
     99     //如果mid > v表示左子树的数可能是后继
    100     if(v < mid && segTree[lson] && (res=Nex(v,lson,l,mid)))
    101         return res;
    102     return Nex(v, rson, mid + 1, r);
    103 }
    104 
    105 int main()
    106 {
    107     //freopen("input.txt", "r", stdin);
    108     scanf("%d", &N);
    109     for(int i = 1; i <= N; i++)
    110     {
    111         scanf("%d %d", &op[i], &Data[i].x);
    112         Data[i].id = i;
    113     }
    114     //离散化预处理
    115     sort(Data  + 1, Data + N + 1, Cmpx);
    116     int cnt = 1;
    117     A[cnt] = Data[1].x;
    118     opx[Data[1].id] = cnt;
    119     for(int i = 2; i <= N; i++)
    120     {
    121         if(Data[i].x != Data[i - 1].x)
    122         {
    123             cnt++;
    124         }
    125         A[cnt] = Data[i].x;
    126         opx[Data[i].id] = cnt;
    127     }
    128     //建树
    129     memset(segTree, 0, sizeof(segTree) );
    130     for(int i = 1; i <= N; i++)
    131     {
    132         switch(op[i])
    133         {
    134             case 1: Update(opx[i], 1, 1, 1, cnt);                   break;
    135             case 2: Update(opx[i], -1, 1, 1, cnt);                  break;
    136             case 3: printf("%d
    ", Rank(opx[i], 1, 1, cnt)+1);      break;
    137             //这里注意第K个数也离散化了!!!
    138             case 4: printf("%d
    ", A[ Kth(A[opx[i]], 1, 1, cnt)] ); break;
    139             case 5: printf("%d
    ", A[ Pre(opx[i], 1, 1, cnt)] );    break;
    140             case 6: printf("%d
    ", A[ Nex(opx[i], 1, 1, cnt)] );    break;
    141         }
    142     }
    143 
    144     return 0;
    145 }
    View Code
  • 相关阅读:
    Hbase实用技巧:全量+增量数据的迁移方法
    求职时这样回答问题你就输了!来自IT类面试官视角的深度解读
    云原生2.0时代:开启应用定义基础设施新时代
    让“物”能说会道,揭晓华为云IOT黑科技
    API生态的发展与机遇:从5000组数据看中国API生态与开发者现状
    如何实现微服务架构下的分布式事务?
    Win32可执行文件的开发过程 Win32汇编语言008
    鱼C加密程序 零基础入门学习Delphi10
    Win32可执行文件的开发过程 Win32汇编语言008
    使用MASM01 Win32汇编语言009
  • 原文地址:https://www.cnblogs.com/dybala21/p/10793405.html
Copyright © 2011-2022 走看看