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 }