codeforces 1028D: Order book

模拟。

考虑每次交易必须选择buy的最大值和sell的最小值

维护一个有序集合$S$,每次ACCEPT操作都会确定剩下的buy集合和sell集合

也就是说,sell的是有序集合的右侧,buy是有序集合的左侧。

我们一直维护sell的最小值$A$和buy的最大值$B$。

对于ACCEPT操作,如果新的元素是在$A$和$B$之间,是合法的

如果既不是$A$,也不是$B$,那么说明这两个sell和buy可以随意选,将答案乘2

再重新确定$A$和$B$的值。

对于ADD操作,我们将其插入有序集合,如果该数小于$B$,大于$A$。

那么这个数目前可以随意的选择(如果重新确定了$A$和$B$就不行了)

最后就是累计的答案乘上可以随意选择的数+1,就是枚举从哪里分开,左边是buy,右边是sell

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define MOD 1000000007
 4 inline int read() {
 5     char ch = getchar(); int x = 0, f = 1;
 6     while(ch < '0' || ch > '9') {
 7         if(ch == '-') f = -1;
 8         ch = getchar();
 9     }
10     while('0' <= ch && ch <= '9') {
11         x = x * 10 + ch - '0';
12         ch = getchar();
13     }
14     return x * f;
15 }
16 char s[20];
17 set<int> S;
18 int mx, mn;
19 int main() {
20     int T = read();
21     S.insert(-1e9);
22     S.insert(1e9);
23     mx = 1e9;
24     mn = -1e9;
25     int wt = 1;
26     int Ans = 1;
27     while(T --) {
28         scanf("%s", s);
29         int x = read();
30         if(s[1] == 'D') {
31             S.insert(x);
32             if(mn < x && x < mx) ++ wt;
33         }
34         else {
35             if(x < mn || x > mx) {
36                 return puts("0"), 0;
37             }
38             if(x != mn && x != mx) {
39                 Ans = Ans * 2 % MOD;
40             } 
41             wt = 1;
42             S.erase(x);
43             set<int> :: iterator it = S.lower_bound(x);
44             mx = *it;
45             mn = *(-- it);
46         }
47     }
48     printf("%d\n", 1ll * Ans * wt % MOD);
49 }

 

posted @ 2018-08-29 20:35  iamunstoppable  阅读(607)  评论(0编辑  收藏  举报