題目大意:
總共有n個人和n個數字
n個人拍成一隊,n個數字也是有順序的
你排在第m個位置
按照順序的每個人可以拿走這個序列中的第一個數字或者最后一個數字
你可以在所有人操作開始前說服最多k個人
讓他們固定拿這個序列的第一個或者是最后一個數字
問你在所有可能的情況中可以拿到的數字的最大值中的最小值(即,到你取得的時候,首尾兩個數字你總是會取最大的那個,問這些數字中的最小值)
※所有沒有被說服的人拿數字是隨機拿的,不存在博弈論中的什么總是拿最大或最小
解題思路:
因為只有說服排在自己前面的人才有用
所以可以先讓 k=min(k,m-1)
每次輪到自己時,場上還會剩下n-m+1個數字,所以先令len=n-m+1
每次在自己前面的人里至少會有m-k-1個人是不受控制的,令rand=m-k-1
先預處理出最后可能的答案所在區間的答案
即取一段長度為len的區間,答案即它的左端點與右端點中的較大值
總共會有n-len+1個區間,即m個區間,將答案存在數組dm中待調用
然后,最多可以說服k個人,貪心可得越多人能被說服則對答案貢獻更大
又因為除了這些被說服的人外,其他排在自己前面的人沒被說服的(隨機的)人的操作方式是不可預判的!!!
所以,這些被說服的人最好能先取,才能讓整個局面更能被自己掌握(確信嘿嘿嘿)
綜上,就可以開始枚舉這k個人里,有多少人取了這個數列的前端,有多少人取了后端
則循環 i=0~k,i 表示有i個人取了前端
那么,這樣取的話最后答案區間就會變成 [i+1,n-i] ,總共會出現rand+1個len長度的可能答案
又因為前面預處理了最后可能的答案
所以最終再循環一次 j=i+1~i+1+rand
取這些答案中的最小值mn
所以這就是這一遍的答案
又因為說服的那些人怎么操作是可控的
所以最終的答案是所有mn中的最大值
#include<bits/stdc++.h> using namespace std; int ar[3550],dm[3550]; void solve(){ int n,m,k,len,rand,i,j,ans=0,mn; cin>>n>>m>>k; k=min(k,m-1); len=n-m+1; rand=m-k-1; for(i=1;i<=n;i++){ cin>>ar[i]; if(i>=len) dm[i-len+1]=max(ar[i],ar[i-len+1]); } for(i=0;i<=k;i++){ mn=0x3f3f3f3f; for(j=i+1;j<=i+1+rand;j++) mn=min(mn,dm[j]); ans=max(ans,mn); } cout<<ans<<'\n'; } int main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int T;cin>>T;while(T--) solve(); return 0; }