1. 程式人生 > >歸併排序【洛谷P1309】

歸併排序【洛谷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也一樣)。