您的位置:首页 > 其它

NOIP2011普及组 瑞士轮

2016-07-26 09:49 344 查看


这道题用暴力其实可以得很多分(感觉70都没问题),但正解还是要用归并排序,每次把队列分成输的和赢得2个队列(看到数据给个2*n才想到的),因为每个队列中本来的顺序不会变,所以直接比较就可以了(排序的时间复杂度O(2*n)。详见代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=200005;
const int inf=200000000;
struct shu
{
int id,w,sum;
}a[maxn];

int n,m,s,b[maxn],c[maxn],d[2][maxn];//直接用2个d数组轮回用就好了(空间换时间)。

int read()
{
int x=0,ok=0;
char ch;
ch=getchar();

while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
while((ch>='0'&&ch<='9')||ch=='-')
{
if(ch=='-') ok=1;
else x=x*10+ch-'0';
ch=getchar();
}

return ok==1?-x:x;
}

bool check(int x,int y)
{
if(a[x].sum==a[y].sum) return a[x].id>a[y].id;
return a[x].sum<a[y].sum;
}
bool check2(int x,int y)
{
if(a[x].sum==a[y].sum) return a[x].id<a[y].id;
return a[x].sum>a[y].sum;
}

void sortt(int p)//归并排序。
{
int j=n,i=0;
while(j>0&&i<n)
{
if(check(d[p][b[j]],d[p][c[n-i]]))
{
d[1-p][2*n-i-n+j]=d[p][b[j]];
j--;
}
else
{
d[1-p][2*n-i-n+j]=d[p][c[n-i]];
i++;
}
}
while(j>0)
{
d[1-p][2*n-i-n+j]=d[p][b[j]];
j--;
}
while(i<n)
{
d[1-p][2*n-i-n+j]=d[p][c[n-i]];
i++;
}
}

void init()
{
n=read();
m=read();
s=read();
for(int i=1;i<=2*n;i++)
{
a[i].sum=read();
a[i].id=i;
}
for(int i=1;i<=2*n;i++)
{
a[i].w=read();
d[0][i]=i;
}
}

void work(int x,int y)//用x来实现2个d数组轮回用。
{
if(y>m)
{
printf("%d",d[x][s]);
return;
}
for(int j=2;j<=2*n;j+=2)
{
if(a[d[x][j]].w>a[d[x][j-1]].w) a[d[x][j]].sum++,b[j/2]=j,c[j/2]=j-1;
else a[d[x][j-1]].sum++,b[j/2]=j-1,c[j/2]=j;
}
sortt(x);
work(1-x,y+1);
}
int main()
{
freopen("swiss.in","r",stdin);
freopen("swiss.out","w",stdout);
init();
sort(d[0]+1,d[0]+1+2*n,check2);
work(0,1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  归并排序 数据