1. 程式人生 > >NOIP模擬——卡牌遊戲

NOIP模擬——卡牌遊戲

mes scanf span ins else bit title body 遊戲

題目

L最近喜歡上了一個卡片遊戲,遊戲規則是: 2個人一共拿2n張卡片,編號1..2n,每個人n張,然後進行n輪出牌,每輪2個人都打一張牌,,點數大的玩家每次獲1分

L可以預測到對方要打牌的順序。

同時,L有一次機會選擇了某個時間點,從那個時候開始,每回合點數少者獲勝。

請你幫助L獲得最大的分數

輸入

第一行是1個整數n

接下來n行表示,對手每次的出牌,根據這些數字,你一定知道了L手上的牌的吧

輸出

1個整數,表示L能獲得最高分數

樣例輸入
4
1
8
4
3
樣例輸出
3
標簽
usaco2015dec
算是有難度的了吧,由於要隨時刪除元素(打出卡牌),所以就用set維護 數組f[i]表示前i個不選擇時間時能拿的最大分數,g[i]表示後i個中選擇時間點能拿的最大分數 則對於每一個a[i]我們選第一個比a[i]大的數,則f[i]=f[i-1]+1;對於每一個a[i]我們選第一個比a[i]小的數,則g[i]=g[i+1]+1;(如果有滿足的數的話) 大佬說可以證明這樣是最優的,可是蒟蒻並不會證 然後就只需要枚舉斷點 找出最大的f[i]+g[i+1]; 代碼
#include<bits/stdc++.h>
using
namespace std; set<int> l,r; bool flag[100005]; int a[50005],g[50005],f[50005],n; int main(){ scanf("%d",&n); int i; memset(flag,true,sizeof(flag)); for(i=1;i<=n;i++) { scanf("%d",&a[i]); flag[a[i]]=false; } for(i=1;i<=2*n;i++) { if(flag[i]) { r.insert(i); l.insert(
-i); } } for( i=1;i<=n;i++) { set<int>::iterator it=r.upper_bound(a[i]); if(it!=r.end()) { r.erase(*it); f[i]=f[i-1]+1; } else f[i]=f[i-1]; } for(i=n;i>=1;i--) { set<int>::iterator it=l.upper_bound(-a[i]); if(it!=l.end()) { l.erase(*it); g[i]=g[i+1]+1; } else g[i]=g[i+1]; } int ans=0; for( i=0;i<=n;i++) { ans=max(ans,f[i]+g[i+1]); } cout<<ans<<endl; }

NOIP模擬——卡牌遊戲