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\n", ans);
229     return 0;
230 }

原文地址:https://www.cnblogs.com/DarkScoCu/p/10527272.html

时间: 2024-12-22 12:13:05

fjutacm 2492 宠物收养所 Splay 模板 O(nlogn)的相关文章

【BZOJ-1208】宠物收养所 Splay

1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6638  Solved: 2601[Submit][Status][Discuss] Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^

刷题总结——宠物收养所(bzoj1208)

题目: Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养所的宠物一个特点值.这样他就能够很方便的处理整个领养宠物的过程了,宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少.1. 被遗弃的宠物过多时,假若到来一个

bzoj1208 宠物收养所treap/splay/set

偷懒用set 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<set> 5 #include<algorithm> 6 #define rep(i,l,r) for(int i=l;i<r;i++) 7 #define update(a) (ans+=a)%=1000000 8 typedef long long ll; 9 using names

C++之路进阶——splay树(宠物收养所)

1285 宠物收养所 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养所的宠物一个特点值.这样他就能够很方便的处理整个领养宠物的过程了,宠物收养所总

1208. [HNOI2004]宠物收养场【平衡树-splay】

Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养所的宠物一个特点值.这样他就能够很方便的处理整个领养宠物的过程了,宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少. 1. 被遗弃的宠物过多时,假若到来一个领养者

BZOJ1208: [HNOI2004]宠物收养所 平衡树 Treap 模板题

Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被 主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希 望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养所的宠物一个特点值.这样他就能够很方便的处理整个领养宠物的过程 了,宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少. 1. 被遗弃的宠物过多时,假若到来一个

BZOJ 1208: [HNOI2004]宠物收养所

1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 7514  Solved: 2982[Submit][Status][Discuss] Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^

洛谷P2286宠物收养场

1 #include<cstdio> 2 #define abs(a,b) (a>b?a-b:b-a) 3 #define MOD 1000000 4 #define MXN 450000+5 5 int read(){ 6 int x=0,w=1; 7 char c=getchar(); 8 while(c<'0'||c>'9'){ 9 if(c=='-') w=-1; 10 c=getchar(); 11 } 12 while(c>='0'&&c&l

[bzoj1208][HNOI2004]宠物收养所

题目好长啊直接copy算了 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养所的宠物一个特点值.这样他就能够很方便的处理整个领养宠物的过程了,宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少. 1. 被遗弃的宠物过多时,假若到来一个领