zoukankan      html  css  js  c++  java
  • fjutacm 2492 宠物收养所 : Splay 模板 O(nlogn)

      1 /**
      2 problem: http://www.fjutacm.com/Problem.jsp?pid=2492
      3 Splay blog: https://tiger0132.blog.luogu.org/slay-notes
      4 函数介绍:
      5 内部函数:
      6     root为指针, x为数值
      7     bool check(int root):返回当前结点为父节点的左结点还是右结点(0为左结点,1为右结点)
      8     void pushUp(int root):旋转后维护结点信息
      9     void rotate(int root):关键函数,旋转结点
     10     void splay(int root, int target = 0):Splay核心,将root结点旋转至target子结点,target为0则旋转到树根
     11     void find(int x): 将数值为x的结点旋转至树根
     12     int pre(int x):寻找数值为x的结点的前驱结点,返回指针
     13     int succ(int x):寻找数值为x的结点的后继节点,返回指针
     14 外部函数:
     15     void clear():清空平衡树
     16     void insert(T x):插入数值为x的数
     17     int rank(T x):返回数值为x的数为第几小
     18     T preAns(T x):返回刚好比数值x小的数是多少
     19     T succAns(T x):返回刚好比数值x大的数是多少
     20     T kth(int k):返回第k小的数是多少
     21     void remove(T x):删除数值为x的结点,如果有多个则数量-1
     22     T top(T x):如果有数值为x的结点返回x,否则返回其他数
     23     int getAllSize():返回平衡树中有多少个数
     24 **/
     25 
     26 #include<stdio.h>
     27 #include<algorithm>
     28 #include<queue>
     29 using namespace std;
     30 
     31 typedef long long ll;
     32 const ll MOD = 1000000;
     33 
     34 template<typename T>
     35 class Splay{
     36     const static int MAXN = 10003;
     37     const static T INF = 0x3f3f3f3f3f3f3f3fLL;
     38 private:
     39     struct Node{
     40         int ch[2];
     41         int cnt, size, parent;
     42         T val;
     43     }node[MAXN];
     44     int treeroot, sign, allSize;
     45     queue<int> freeMemory;
     46     bool check(int root){ /// right return 1 else return 0
     47         return node[node[root].parent].ch[1] == root;
     48     }
     49     void pushUp(int root){
     50         node[root].size = node[node[root].ch[0]].size + node[node[root].ch[1]].size + node[root].cnt;
     51     }
     52     void rotate(int root){
     53         int father = node[root].parent, grandpa = node[father].parent, direction = check(root), child = node[root].ch[direction^1];
     54         node[father].ch[direction] = child; node[child].parent = father;
     55         node[grandpa].ch[check(father)] = root; node[root].parent = grandpa;
     56         node[root].ch[direction^1] = father; node[father].parent = root;
     57         pushUp(father); pushUp(root);
     58     }
     59     void splay(int root, int target = 0){ /// if target == 0 then root to treeroot
     60         while(node[root].parent != target){
     61             int father = node[root].parent, grandpa = node[father].parent;
     62             if(grandpa != target){
     63                 if(check(root) == check(father)) rotate(father);
     64                 else rotate(root);
     65             }
     66             rotate(root);
     67         }
     68         if(!target) treeroot = root;
     69     }
     70     void find(int x){
     71         if(!treeroot) return;
     72         int cur = treeroot;
     73         while(node[cur].ch[x > node[cur].val] && node[cur].val != x){
     74             cur = node[cur].ch[x > node[cur].val];
     75         }
     76         splay(cur);
     77     }
     78     int pre(int x){
     79         find(x);
     80         if(node[treeroot].val < x) return treeroot;
     81         if(!node[treeroot].ch[0]) return -1;
     82         int cur = node[treeroot].ch[0];
     83         while(node[cur].ch[1]){
     84             cur = node[cur].ch[1];
     85         }
     86         return cur;
     87     }
     88     int succ(int x){
     89         find(x);
     90         if(node[treeroot].val > x) return treeroot;
     91         if(!node[treeroot].ch[1]) return -1;
     92         int cur = node[treeroot].ch[1];
     93         while(node[cur].ch[0]){
     94             cur = node[cur].ch[0];
     95         }
     96         return cur;
     97     }
     98 public:
     99     void clear(){
    100         sign = 0;
    101         insert(INF);
    102         insert(-INF);
    103         allSize = 0;
    104     }
    105     void insert(T x){
    106         allSize ++;
    107         int cur = treeroot, preroot = 0;
    108         while(cur && node[cur].val != x){
    109             preroot = cur;
    110             cur = node[cur].ch[x > node[cur].val];
    111         }
    112         if(cur){
    113             node[cur].cnt ++;
    114         }else{
    115             if(freeMemory.empty())
    116                 cur = ++ sign;
    117             else{
    118                 cur = freeMemory.front();
    119                 freeMemory.pop();
    120             }
    121             if(preroot) node[preroot].ch[x > node[preroot].val] = cur;
    122             node[cur].val = x;
    123             node[cur].cnt = 1;
    124             node[cur].ch[0] = node[cur].ch[1] = 0;
    125             node[cur].size = 1;
    126             node[cur].parent = preroot;
    127         }
    128         splay(cur);
    129     }
    130     int rank(T x){
    131         find(x);
    132         return node[node[treeroot].ch[0]].size;
    133     }
    134     T preAns(T x){
    135         return node[pre(x)].val;
    136     }
    137     T succAns(T x){
    138         return node[succ(x)].val;
    139     }
    140     T kth(int k){
    141         k ++;
    142         int cur = treeroot;
    143         while(1){
    144             if(node[cur].ch[0] && k <= node[node[cur].ch[0]].size){
    145                 cur = node[cur].ch[0];
    146             }else if(k > node[node[cur].ch[0]].size + node[cur].cnt){
    147                 k -= node[node[cur].ch[0]].size + node[cur].cnt;
    148                 cur = node[cur].ch[1];
    149             }else{
    150                 return node[cur].val;
    151             }
    152         }
    153     }
    154     void remove(T x){
    155         allSize --;
    156         int last = pre(x), next = succ(x);
    157         splay(last), splay(next, last);
    158         int del = node[next].ch[0];
    159         if(node[del].cnt > 1){
    160             node[del].cnt --;
    161             splay(del);
    162         }else{
    163             freeMemory.push(node[next].ch[0]);
    164             node[next].ch[0] = 0;
    165         }
    166     }
    167     T top(T x){
    168         find(x);
    169         return node[treeroot].val;
    170     }
    171     int getAllSize(){
    172         return allSize;
    173     }
    174 };
    175 
    176 Splay<ll> splay;
    177 
    178 int main(){
    179     int n;
    180     ll ans = 0;
    181     bool type = 1;
    182     scanf("%d", &n);
    183     splay.clear();
    184     while(n --){
    185         int a;
    186         ll b;
    187         scanf("%d%lld", &a, &b);
    188         if(a){
    189             if(type || splay.getAllSize() == 0){
    190                 splay.insert(b);
    191                 type = 1;
    192             }
    193             else{
    194                 ll pre = splay.preAns(b), mid = splay.top(b), succ = splay.succAns(b);
    195                 ll choose;
    196                 if(abs(pre - b) <= abs(mid - b)){
    197                     choose = pre;
    198                 }else{
    199                     choose = mid;
    200                 }
    201                 if(abs(choose - b) > abs(succ - b)){
    202                     choose = succ;
    203                 }
    204                 ans = (ans + abs(choose - b)) % MOD;
    205                 splay.remove(choose);
    206             }
    207         }else{
    208             if(!type || splay.getAllSize() == 0){
    209                 splay.insert(b);
    210                 type = 0;
    211             }
    212             else{
    213                 ll pre = splay.preAns(b), mid = splay.top(b), succ = splay.succAns(b);
    214                 ll choose;
    215                 if(abs(pre - b) <= abs(mid - b)){
    216                     choose = pre;
    217                 }else{
    218                     choose = mid;
    219                 }
    220                 if(abs(choose - b) > abs(succ - b)){
    221                     choose = succ;
    222                 }
    223                 ans = (ans + abs(choose - b)) % MOD;
    224                 splay.remove(choose);
    225             }
    226         }
    227     }
    228     printf("%lld
    ", ans);
    229     return 0;
    230 }
  • 相关阅读:
    EEPROM与FLASH
    Sublime Markdown预览插件安装流程
    挖矿算法比较(转)
    CPU based record
    MVC学习之数据库开发模式:三种开发模式总结:
    MVC学习之数据库开发模式:模型优先实例介绍
    MVC学习之数据库开发模式:代码优先实例介绍
    MVC学习之数据库开发模式:数据库优先实例介绍
    DataSet之将连个DataSet集合合并成一个DataSet集合
    索引和长度必须引用该字符串内的位置。参数名: length
  • 原文地址:https://www.cnblogs.com/DarkScoCu/p/10527272.html
Copyright © 2011-2022 走看看