題目意思:給你兩個數組w和s,要求每次第一名(a[1])和第二(a[2])、第三和第四、第五和第六、第i(i+1<=n)和i+1名比賽,如果a[i].w>a[i+1].w則a[i].s++,然後重新按照a[i].s排序,重複以上操作直到操作次數等於R爲止。求此時的A[Q].id
不難想到暴力算法,先把a排序,然後順序掃描整個a如果a[i].w>a[i+1].w則a[i].s++,然後再快排一次。
時間複雜度爲O(R*(2*n)*log2(2*n))對於本題n<=100000,R<=50的規模
運算次數爲50*200000*18=1.8億次,會超時。
正解,設一個數組Win存儲這一輪贏了的人,Lose存儲輸的。
依然是順序掃描a,把贏了的人放入Win中,輸了的放入Lose中。
然後把Win和Lose按照cmp來合併,合併後的數組就是新的a,更新a,繼續下一次歸併排序直到次數等於R,輸出答案;
這種做法由於是直接合並,掃描是O(2*n)的,所以最後的時間複雜度是O(R*2*n)就可以過了。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#define maxn 100005
#define inf 1000000010
using namespace std;
int n,R,Q;
struct data
{
int id,s,w;
}Win[2*maxn],Lose[2*maxn],Ans[2*maxn];
bool cmp(data a,data b)
{
return a.s>b.s || (a.s==b.s && a.id<b.id);
}
void solve()
{
int ai=1,bi=1;
for(int i=1;i<=2*n;i+=2)
{
if(Ans[i].w<Ans[i+1].w)
{
Ans[i+1].s++;
Win[ai++]=Ans[i+1];
Lose[bi++]=Ans[i];
}
else
{
Ans[i].s++;
Win[ai++]=Ans[i];
Lose[bi++]=Ans[i+1];
}
}
int i=1,j=1,k=1;
while(i<ai && j<bi)
{
if(cmp(Win[i],Lose[j]))
{
Ans[k++]=Win[i];
i++;
}
else
{
Ans[k++]=Lose[j];
j++;
}
}
while(i<ai)Ans[k++]=Win[i++];
while(j<bi)Ans[k++]=Lose[j++];
}
int main()
{
//freopen("my.in","r",stdin);
//freopen("my.out","w",stdout);
scanf("%d%d%d",&n,&R,&Q);
for(int i=1;i<=2*n;i++)
{
scanf("%d",&Ans[i].s);
Ans[i].id=i;
}
for(int i=1;i<=2*n;i++)
scanf("%d",&Ans[i].w);
sort(Ans+1,Ans+2*n+1,cmp);
for(int i=1;i<=R;i++)
solve();
printf("%d\n",Ans[Q].id);
return 0;
}