zoukankan      html  css  js  c++  java
  • [USACO15DEC]High Card Low Card (Platinum)

    https://www.zybuluo.com/ysner/note/1300791

    题面

    贝西和她的朋友艾尔西正在玩这个简单的纸牌游戏。游戏有(2N)张牌,牌上的数字是(1)(2N)。把这些牌分成两份,贝西有(N)张,艾尔西有另外(N)张。接下来她们进行(N)轮出牌,每次各出一张牌。一开始,谁出的牌上的数字大,谁就获得这一轮的胜利。贝西有一个特殊权利,她可以在任意一个时刻把原本数字大的获胜的规则改成数字小的获胜,这个改变将会一直持续到游戏结束。特别的,贝西可以从第一轮开始就使用小牌获胜的规则,也可以直到最后一轮都还不使用大牌获胜的规则。
    现在,贝西已经知道了艾尔西出牌的顺序,她想知道她最多能够赢多少轮。

    解析

    显然前面每次选择比对方大却又尽可能小的牌,后面选择比对方小却又尽可能大的牌。
    其实这就是田径赛马的原理。

    支持删除和二分查找,显然(set)
    然后分别从前后预处理应该出什么牌,最后枚举中介点就行。

    问题出在具体实现上。
    后一个过程其实可以用一个存负值的(set)来搞。
    而不是像蒟蒻一样用一个存正值的(set)然后(TLE)半天。

    还有(lower\_bound)没找到结果会返回(end())

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #define ll long long
    #define fp(i,a,b) for(int i=a;i<=b;++i)
    #define fq(i,a,b) for(int i=a;i>=b;--i)
    using namespace std;
    const int N=5e5+100;
    int n,a[N],q[N],h[N],ans;
    bool vis[N];
    set<int>S1,S2;
    set<int>::iterator it;
    int main()
    {
      scanf("%d",&n);
      fp(i,1,n) scanf("%d",&a[i]),vis[a[i]]=1;
      fp(i,1,2*n) if(!vis[i]) S1.insert(i),S2.insert(-i);
      fp(i,1,n)
        {
          it=S1.lower_bound(a[i]);
          if(it!=S1.end())
        {
          q[i]=q[i-1]+1;
          S1.erase(it);
        }
          else q[i]=q[i-1],S1.erase(*S1.begin());
        }
      fq(i,n,1)
        {
          it=S2.lower_bound(-a[i]);
          if(it!=S2.end())
        {
          h[i]=h[i+1]+1;
          S2.erase(it);
        }
          else h[i]=h[i+1],S2.erase(*S2.begin());
        }
      fp(i,0,n) ans=max(ans,q[i]+h[i+1]);
      printf("%d
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    Linux:正则表达式2
    Linux:基础命令三
    Linux:正则表达式1
    虚拟机:主机能ping通虚拟机,虚拟机不可以ping通主机
    Linux:安装禅道
    ssh免密钥登录
    CKA-Harbor简单使用
    CKA-docker部署LNMP网站平台
    CKA-构建Nginx、PHP、Tomcat镜像
    CKA-docker卸载以及安装
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9743977.html
Copyright © 2011-2022 走看看