歸併排序【洛谷P1309】
阿新 • • 發佈:2018-11-10
先上題目: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也一樣)。