NOIP模擬——卡牌遊戲
阿新 • • 發佈:2018-10-02
mes scanf span ins else bit title body 遊戲
題目
算是有難度的了吧,由於要隨時刪除元素(打出卡牌),所以就用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]; 代碼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
#include<bits/stdc++.h> usingnamespace 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模擬——卡牌遊戲