归并排序【洛谷P1309】

先上题目:https://www.luogu.org/problemnew/show/P1309

拿到这个题目,我不屑一顾,暴力搞搞就完事了,直到看到数据范围,我才对着电脑思考了好久...

暴力搞一波的复杂度大概是O(r*n*logn)的,怀着侥幸的心理,果然T了四组数据。

下面是题解,表达能力有限,大概只有我自己能看懂(大概只有我自己才会看这篇博客吧)

1.首先按每个人的s和编号,sort一遍。

2.第一步sort了之后的数组是有序的了,那么接下来的操作都是在有序的基础上进行的(大家应该知道归并排序,这个不就是个归并的过程嘛)。每一次比赛,都将赢得和输得人分别存在twin和tlose中,然后直接归并,twin和tlose都是有序的(原本是有序的,s++和不加,拿到分别的twin和tlose中都是有序的),所以复杂度就从O(nlogn)降到了O(n)。整体复杂度从O(r*n*logn)降到了大概O(r*n),(但是第一次还是有一个sort,我没算进去。)

下面是代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+7;
struct node
{
	ll s;
	ll w;
	int q;
}Q[maxn],twin[maxn],tlose[maxn];
bool cmp(node a,node b)
{
	if(a.s==b.s)
	{
		return a.q<b.q;
	}
	return a.s>b.s;
}
int main()
{
	int n,r,rk;
	while(~scanf("%d%d%d",&n,&r,&rk))
	{
		for(int i=1;i<=2*n;i++)
		{
			Q[i].q = i;
			scanf("%lld",&Q[i].s);
		}
		for(int i=1;i<=2*n;i++)
		{
			scanf("%lld",&Q[i].w);
		}
		sort(Q+1,Q+1+2*n,cmp);
	
		for(int k=0;k<r;k++)
		{
			int pw = 0,pl = 0;
			for(int i=1;i<2*n;i+=2)
			{
				if(Q[i].w>Q[i+1].w)
				{
					Q[i].s++;
					twin[++pw] = Q[i];
					tlose[++pl] = Q[i+1];
				}
				else
				{
					Q[i+1].s++;
					twin[++pw] = Q[i+1];
					tlose[++pl] = Q[i];
				}
			}
			merge(twin+1,twin+1+pw,tlose+1,tlose+1+pl,Q+1,cmp);
		}
		cout<<Q[rk].q<<endl;
	}
	return 0;
}

因本菜鸡太懒了,太蒻了,所以,讲解不仅逻辑不清而且题目还很简单。

PS:(这是本蒻鸡的第一篇题解,希望以后可以坚持下去,碰见好的题目一定尽量都发来)

PPS:忘了一件重要的事情,STL的merge的用法是:前面给俩个数组的迭代器,然后传一个数组的开头,最后跟一个cmp(vector也一样)。

猜你喜欢

转载自blog.csdn.net/KIKO_caoyue/article/details/83087805
今日推荐