非常思维的一道题目,题意很长
给定s1,s2两个集合,s1维护最大值,s2维护最小值,s1的所有元素要比s2小
操作1:往两个集合里的任意一个添加x
操作2:把x从所在的集合里删掉:要求被删的x必须是s1里最大的元素或s2里最小的元素
因为操作2的要求十分严格。。我们可以想到在最后一次操作2结束前所有的操作1都是确定下来的
那我们先来考虑最后一次操作2之前的操作1:
每次加x,但是不知道x往哪里加,那就直接用一个大集合S,把x加进去
直到出现一个操作2:操作2给出的x必然在集合S的某个位置,那比x小的元素必定被划分到集合s1中,比x大的元素被划分到s2中,此时之前的操作添加的数都有确定的位置了,并且两个集合的最大值L,最小值R也确定下来了
然后接下去的操作1就是往集合里面加元素,操作2就进行重新划分+更新L,R,并且每次操作2都有两种选择,即x从s1里删去还是从s2里删去 ( 除了两种特殊情况:无解和x恰好==L,R边界 )
最后一次操作2后,cnt次操作1添加的数都没有确定的划分,所以再乘上cnt+1种选择
#include<bits/stdc++.h> #include<set> using namespace std; #define ll long long #define maxn 400005 #define mod 1000000007 #define INF 0x3f3f3f3f3f3f ll n,x,L,R; char op[100]; set<ll>s; set<ll>::iterator it; int main(){ cin>>n;ll ans=1; L=-INF,R=INF; s.insert(INF);s.insert(-INF); it=s.begin(); int cnt=0; for(int i=1;i<=n;i++){ scanf("%s%lld",op,&x); if(op[1]=='D'){ if(x>=L && x<=R)cnt++; s.insert(x); } else { cnt=0; if(x<L || x>R){ puts("0"); return 0; } else if(x!=L && x!=R)ans=ans*2%mod; //这里要注意因为所有的元素都不相等,所以当要删除边界时只有一种选择 it=s.lower_bound(x); it++;R=*it; it--;it--;L=*it; it++;s.erase(it); } } cout<<ans*(++cnt)%mod<<endl; }