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 }