題目傳送
思路非常簡單,只要開始時把結構體排個序,每次給贏的加分再排序,共r次,最後再輸出分數第q大的就行了。
(天真的我估錯時間複雜度用每次用sort暴力排序結果60分。。。)
實際上這道題估算時間複雜度時o括號裡的n並不是輸入的n,而是輸入的n乘2,這就要求我們精準地估算時間複雜度以採取合適的演算法來解題。顯然sort時不行的。為什麼sort這麼強都會tle?考慮不行的原因,找找有用的教訓:(先普及一下:sort是氣泡排序的改進版,平均時間複雜度為o(n log n),最壞情況下會退化成o(n2)。)
從sort的原理開始考慮:sort排序時會有兩個指標分別從頭到尾相向而行直到相遇後的分手。然後再分別對左右兩部分遞迴,直到遞迴的區間長度為1。這樣發現,就算這個序列已經有序(或基本有序)時,sort會造成大量的時間浪費。這時同時o(n log n)級別的歸併排序就不同了。當序列基本有序時,歸併排序會造成更少的時間浪費,因為序列基本有序時,「並」操作左右兩區間中的左區間應該是主要都小於右區間的,這樣就會使左區間更早地併入答案陣列,剩下的右區間的長度相應地更長,用個memcpy就完事了,結果是使使左右區間的開頭端點比較的次數減少,進而減少了時間浪費。
發現把乙個大輪迴比賽裡的所有贏家單獨拿出來後他們的順序都是合法且不變的(因為都是從原來的序列中的相應值加1);所有輸家的大小順序也是合法的(因為值都沒有改變)。這樣可以直接用歸併排序的思想,把贏家都放在乙個區間、輸家放在另乙個區間中,兩個區間只要歸併一次就能得到有序的數列了,無需再各種遞迴費解合併。
見ac**:
1 #include2 #include3 #include4 #include5 #include6還是要做好時間複雜度估計的說!7using
namespace
std;89
struct
huma[200003],win[100005],lose[100005];//
贏的放一起,輸的放一起
1213
intn,r,q,ans,lw,ll;
1415
char
ch;16
17bool
cmp(hum a,hum b)
1821
22 inline int
read()
2330
31int
main()
3239
for(int i=1;i<=n;i++) a[i].w=read();
40 sort(a+1,a+n+1
,cmp);
41for(int k=1;k<=r;k++)
4251
else
5257}58
int l=1,r=1,len=1;//
往下都是並的過程
59while(l<=lw&&r<=ll)
6070}71
if(l<=lw) memcpy(a+len,win+l,sizeof(hum)*(lw-l+1
));72
if(r<=ll) memcpy(a+len,lose+r,sizeof(hum)*(ll-r+1));//
並的過程結束
73 lw=0;ll=0; //
因為是由字首++維護,所以要初始化為1 74}
75 cout<
76return0;
77 }
洛谷P1309 瑞士輪
本題同樣是noip普及組第三題。因為太久沒有做過題目了,先從普及組開始練習吧。題目內容 很顯然想到的思路就是模擬,如下 include include include include using namespace std struct player bool cmp player a,player...
洛谷p1309 瑞士輪
因為太菜不會寫p1310 表示式的值,就只能過來水兩篇部落格啦qwq 另外這個題我是開o2才過的 雖然是寫了歸併排序 可能我太菜寫的歸併不是還可以 剪枝 吧qwq 哎,果真還是太菜啦qwq 所以準備寫歸併然後去題解學習正確的不用開o2就可以過的演算法 瑞士輪 題目鏈結 其實這個題打眼一看可以直接so...
洛谷 P1309 瑞士輪
在雙人對決的競技性比賽,如桌球 羽毛球 西洋棋中,最常見的賽制是淘汰賽和迴圈賽。前者的特點是比賽場數少,每場都緊張刺激,但偶然性較高。後者的特點是較為公平,偶然性較低,但比賽過程往往十分冗長。本題中介紹的瑞士輪賽制,因最早使用於1895年在瑞士舉辦的西洋棋比賽而得名。它可以看作是淘汰賽與迴圈賽的折中...