题目链接:
题目大意:
给定2N个人(N<=100 000)和其初始分数、能力值(能力两两不同),比赛M次(M<=50),每次PK都是按分数排序后第1和第2比,第3和第4比....能力高的获胜,问比M次后第Q个人是谁。
题目思路:
【单调队列】
略加思索,我们不难发现,每次比赛获胜的人和失败的人分别组成了两个按分数递减的队列。
于是一开始快排一下,接着可以按照归并排序的思路,每次比完将获胜的人和失败的人合并。时间复杂度就降到O(N*M)了。
(一开始就随手写了个快排m次的暴力程序,丢上去只有70分,只好好好写代码了)
1 // 2 //by coolxxx 3 // 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 #include<iomanip> 8 #include<memory.h> 9 #include<time.h> 10 #include<stdio.h> 11 #include<stdlib.h> 12 #include<string.h> 13 #include<stdbool.h> 14 #include<math.h> 15 #define min(a,b) ((a)<(b)?(a):(b)) 16 #define max(a,b) ((a)>(b)?(a):(b)) 17 #define abs(a) ((a)>0?(a):(-(a))) 18 #define lowbit(a) (a&(-a)) 19 #define sqr(a) (a)*(a) 20 #define swap(a,b) (a)^=(b),(b)^=(a),(a)^=(b) 21 #define eps 1e-8 22 #define MAX 0x7f7f7f7f 23 #define INF 20000 24 #define PI 3.1415926535897 25 #define N 100004 26 using namespace std; 27 int n,m,lll,ans,cas; 28 struct xxx 29 { 30 int num,s,p; 31 }a[N<<1],w[N],l[N]; 32 bool cmp(xxx aa,xxx bb) 33 { 34 if(aa.s!=bb.s)return aa.s>bb.s; 35 return aa.num<bb.num; 36 } 37 int main() 38 { 39 #ifndef ONLINE_JUDGE 40 // freopen("1.txt","r",stdin); 41 // freopen("2.txt","w",stdout); 42 #endif 43 int i,j,k; 44 while(~scanf("%d",&n) && n) 45 { 46 scanf("%d%d",&m,&cas); 47 n<<=1; 48 for(i=1;i<=n;i++) 49 { 50 a[i].num=i; 51 scanf("%d",&a[i].s); 52 } 53 for(i=1;i<=n;i++) 54 scanf("%d",&a[i].p); 55 sort(a+1,a+1+n,cmp); 56 w[(n>>1)+1].s=l[(n>>1)+1].s=-MAX; 57 for(i=1;i<=m;i++,lll=0) 58 { 59 for(j=1;j<=n;j+=2) 60 { 61 if(a[j].p>a[j+1].p) 62 { 63 a[j].s++; 64 w[++lll]=a[j]; 65 l[lll]=a[j+1]; 66 } 67 else 68 { 69 a[j+1].s++; 70 w[++lll]=a[j+1]; 71 l[lll]=a[j]; 72 } 73 } 74 for(j=1,k=1;j<=(n>>1)+1 && k<=(n>>1)+1;) 75 if(w[j].s>l[k].s || (w[j].s==l[k].s && w[j].num<l[k].num)) 76 a[j+k-1]=w[j++]; 77 else 78 a[j+k-1]=l[k++]; 79 } 80 printf("%d\n",a[cas].num); 81 } 82 return 0; 83 } 84 85 86 /* 87 // 88 89 // 90 */