2018CCPC桂林 A(貪心,思維)

2022-07-11 00:18:11 字數 1196 閱讀 5538

題目

分析:首先發現將大的數放在小的數前面結果更優,於是想到通過比較元素大小的方式將兩個陣列合併,大的放前面小的放後面,但很容易就能想到比這樣合併更優的方案。一開始我是想先按這種方式進行合併,然後將最後未合併完的剩餘陣列元素向前推進插值,維護乙個雙端佇列儲存推進元素塊的資訊,藉此更新答案,但寫到一半想到了反例,又想了想感覺沒有解決的辦法,原因在於這種方式過於區域性,很難顧及全域性。如果要合併的兩個陣列原本就是單調不增序列那按照一開始的想法直接比較兩陣列元素大小進行合併就好了,這樣最終答案是正確的。此時就可以開始亂想,如果想到平均值就好辦了,通過類似單調棧的方式將原本陣列劃分為多個區塊,滿足區塊的平均值單調不增,然後就可以按照一開始的想法合併陣列了。然後我們大致證明一下可以感覺到這樣最優的,即不存在交換兩個元素使結果優於以這種方式合併陣列的答案。

#include#include#define fi first

#define se second

using namespace std;

typedef long long ll;

const int n = 1e5 + 50;

int t, n, m;

int a[n], b[n], c[n << 1], id[n << 1];

pairda[n], db[n];

int main();

while(len_a > 1 && da[len_a].fi * da[len_a - 1].se > da[len_a - 1].fi * da[len_a].se);}}

for(int i = 1; i <= m; ++i);

while(len_b > 1 && db[len_b].fi * db[len_b - 1].se > db[len_b - 1].fi * db[len_b].se);

}}

while(x <= len_a && y <= len_b)

dy += db[y++].se;

}else

dx += da[x++].se;}}

while(x <= len_a)

dx += da[x++].se;

}while(y <= len_b)

dy += db[y++].se;

}printf("case %d: %lld\n", ca, ans);

}return 0;

}

2018ccpc吉林 C JUSTICE 思維

題意 n個物品,每個物品重量1 2 k i 問可不可以分成兩份,讓這兩份的總量都大於1 2 題解 因為兩份都要大於1 2,那麼我們兩份都找出1 2,剩下的就無所謂了。我們把問題轉化為,兩份都需要找到乙個1,因為 1 2 1 4 1 4,所以乙個1等價於兩個2,4個3.我們先從小到大排個序,令cnt1...

2018CCPC吉林C JUSTICE(思維模擬)

題意 給你n個數,能否分成兩組,使每組的2的ki次方分之一的和大於等於二分之一,能的話輸出分組方案 思路 不難發現,例,也就是2個k能合成乙個k 2,能不能分成兩組,只需要看最後合完之後1的個數是不是大於等於2。利用二進位制的原理,優先佇列 並查集,先取出權值最小的,進行合併,如果兩個值相同,則可以...

2018CCPC網路賽A(優先佇列,思維)

include using namespace std priority queue q int main q.push 賣出 tmp x q.top first 如果前面沒有比它更小的,相當於放進去乙個標記為1的 如果有比它更小的,相當於執行買賣 if q.top second 1 除了第一次進佇...