sharepoint是什么-金山卫士手机版

noip2011
2023年4月3日发(作者:winiso下载)

对于100%的数据,1≤N≤100,000,1≤R≤50,1≤Q≤2N,0≤s1,s2,…,s2N

≤10^8,1≤w1,w2,…,w2N≤10^8。

这个数据告诉我们:使用快速排序只能拿到50-60分。可是我却把它直接忽略了。

(不知道怎么回事,我写了快速排序只拿到了10分,后面的40分莫名其妙丢掉了,不知道

为什么。)

现在我是C++的OIER,所以就直接使用C++的sort函数(sort当然不能AC50分)。

我在vijos50分的代码:

#include

#include

#include

#include

#include

#include

usingnamespacestd;

structsportsman

{

intid,score,power;

}V[200005];

intN,R,Q;

voidstart_contest()

{

for(inti=1;i<=N;i+=2)

if(V[i].power>V[i+1].power)

V[i].score++;

else

V[i+1].score++;

}

boolcompare(sportsmana,sportsmanb)

{

if(==)

<;

else

>;

}

intmain()

{

//freopen("","r",stdin);

scanf("%d%d%d",&N,&R,&Q);

N*=2;

for(inti=1;i<=N;i++)

{

V[i].id=i;

intscore;

scanf("%d",&score);

V[i].score=score;

}

for(inti=1;i<=N;i++)

{

intpower;

scanf("%d",&power);

V[i].power=power;

}

sort(V+1,V+N+1,compare);

for(inti=1;i<=R;i++)

{

start_contest();

sort(V+1,V+N+1,compare);

}

printf("%dn",V[Q].id);

return0;

}

然后我就想到了优化最后一轮比赛(调用nth_element函数优化)

不过根本也没有优化多少,还是50分。与原通过数据比起来,优化63ms

代码:

#include

#include

#include

#include

#include

#include

usingnamespacestd;

structsportsman

{

intid,score,power;

}V[200005];

intN,R,Q;

voidstart_contest()

{

for(inti=1;i<=N;i+=2)

if(V[i].power>V[i+1].power)

V[i].score++;

else

V[i+1].score++;

}

boolcompare(sportsmana,sportsmanb)

{

if(==)

<;

else

>;

}

intmain()

{

//freopen("","r",stdin);

scanf("%d%d%d",&N,&R,&Q);

N*=2;

for(inti=1;i<=N;i++)

{

V[i].id=i;

intscore;

scanf("%d",&score);

V[i].score=score;

}

for(inti=1;i<=N;i++)

{

intpower;

scanf("%d",&power);

V[i].power=power;

}

sort(V+1,V+N+1,compare);

for(inti=1;i<=R;i++)

if(i!=R)

{

start_contest();

sort(V+1,V+N+1,compare);

}

else

{

start_contest();

nth_element(V+1,V+Q,V+N+1,compare);

printf("%dn",V[Q].id);

}

return0;

}

最后实在是想不出对源程序的优化了。憋了很久,终于想出了一个归并的优化(AC,基于

STLalgorithmmerge函数):

首先,还是要使用sort对N*2个选手进行排序(我重载比较符号,来实现选手之间的大小),

注意:只进行一轮!

然后,我们开两个vector,分别记录失败者和胜利者信息,最后我们调用STLalgorithmmerge

函数将这两个vector合并到一个result容器中就行了。

为什么这个方法行的通?如果两个选手的分数相同,编号小的要排在前面,怎么做到呢?

我们可以再来想一下归并排序,归并排序是一个稳定的排序(相当与stable_sort),所以merge

函数可以保证原来选手位置的相对顺序!(只可惜我这次NOIP的语言不是C++。)

再来比较一下使用sort函数merge函数的时间复杂度:

sort函数:很明显:O(NlogN*R)

merge函数:合并一轮是O(n)的复杂度,所以复杂度就是:O(Rn)。这个算法显然可以通过,

N假设是10万,R假设是50,也不过是进行了500万次操作,1秒钟肯定可以通过最强数

据。

最后我们只要输出result[Q].idnum就行了。

代码:

#include

#include

#include

#include

#include

#include

#include

usingnamespacestd;

structsportsman

{

intid,score,power;

booloperator>(constsportsman&t)const

{

if(==score)

returnid<;

else

returnscore>;

};

}result[200005];

vectorwin,lose;

intN,R,Q;

voidstart_contest()

{

for(inti=0;i

{

if(result[i].power>result[i+1].power)

{

result[i].score++;

_back(result[i]);

_back(result[i+1]);

}

else

{

result[i+1].score++;

_back(result[i+1]);

_back(result[i]);

}

}

}

intmain()

{

//freopen("","r",stdin);

//freopen("","w",stdout);

intscore,power;

scanf("%d%d%d",&N,&R,&Q);

N*=2;

for(inti=0;i

{

scanf("%d",&score);

result[i].id=i+1;

result[i].score=score;

}

for(inti=0;i

{

scanf("%d",&power);

result[i].power=power;

}

sort(result,result+N,greater());

for(inti=0;i

{

start_contest();

merge((),(),(),(),result,greater());

();

();

}

printf("%dn",result[Q-1].id);

return0;

}

评测结果:

#01:Accepted(0ms,2688KB)

#02:Accepted(0ms,2688KB)

#03:Accepted(0ms,2692KB)

#04:Accepted(0ms,2948KB)

#05:Accepted(0ms,3196KB)

#06:Accepted(53ms,3692KB)

#07:Accepted(193ms,4624KB)

#08:Accepted(443ms,6548KB)

#09:Accepted(521ms,6548KB)

#10:Accepted(631ms,6548KB)

Accepted/100/1843ms/6548KB

可见,前5个数据0ms秒杀,后面的数据所花费的时间逐渐递升,至少时间都控制在600ms

左右。

更多推荐

noip2011