zoukankan      html  css  js  c++  java
  • 集合划分——cf1028D思维题

    非常思维的一道题目,题意很长

    给定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;    
    } 
  • 相关阅读:
    Android_EditText
    JAVA_Gson_example
    JAVA_Gson
    JAVA_eclipse 保留Java文件时自动格式化代码和优化Import
    JAVA_JSON_example
    JAVA_JSON
    JAVA_HttpClientUtils
    Android_Gallery
    JAVA_JDBC
    day05 Pyhton学习
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10816108.html
Copyright © 2011-2022 走看看