1. 程式人生 > >CSUST-17級集訓隊選拔賽解題報告

CSUST-17級集訓隊選拔賽解題報告

人生 display 元素 lap 查詢 node define 維護 技術分享

摸了一個寒假的魚,賽前各種被奶,就感覺自己要涼,我的感覺向來是對的,結果真的涼透了QAQ。

開場就是裸題各種bug各種WA,心態爆炸,確實還是造成了不小的影響。後面真的懷疑人生到不想寫,掛機(然後被罵了orz)。我每次都控制不好比賽的心態和節奏唉_(:з」∠)_

比較意外的是小夥伴們和大佬們也emmmm 涼得挺厲害……跟學長們同時期是完全不能比的吧……直接造成了我們有個一周的contest補題……

補完之後的感受是……真的基本都是裸題。然而賽場上發揮正常最多也只是再出1題2題,很多地方都差臨門一腳的感覺,前段時間死磕DP感覺會一點了,比賽的時候還是一個也沒做出來= =。暴力又不敢打。補題暴力A的時候真是心情復雜……真的是明白了什麽叫菜是原罪

下周ccf,下下周多校,下下下周C4和藍橋杯,有幾位新大佬我都沒他們一半努力,我可能要搶救一下。

A. 災區重建

題意:N個城市由M條道路互相連通,每條道路最大承重量是w,要選出一條從一個城市到達另外N-1個城市的路徑使一次能承受的重量最大,求這個最大重量

數據範圍:T組樣例(T <= 10), N <= 1e5, M <= 1e6, u,v <= N, w <= 1e9

思路:一條路徑能承受的最大重量是這幾條路w的最小值,連通N個節點只需要N-1條邊,把所有邊按從大到小排序,求出一棵最大生成樹,最小的那條邊就是答案

技術分享圖片
 1 #include<cstdio>
 2
#include<algorithm> 3 #define INF 0x3f3f3f3f 4 using namespace std; 5 6 const int mx = 1e6+10; 7 int pa[mx]; 8 9 struct edge{ 10 int u, v, w; 11 edge(int u = 0, int v = 0, int w = 0): u(u), v(v), w(w){} 12 bool operator < (const edge& a) const{ 13 return w > a.w;
14 } 15 }e[mx]; 16 17 int findset(int x){ 18 return pa[x] == x ? x : pa[x] = findset(pa[x]); 19 } 20 21 int main(){ 22 int t, kase = 0; 23 scanf("%d", &t); 24 while (t--){ 25 for (int i = 0; i < mx; i++) pa[i] = i; 26 int n, m, u, v, w; 27 scanf("%d%d", &n, &m); 28 for (int i = 0; i < m; i++){ 29 scanf("%d%d%d", &u, &v, &w); 30 e[i] = edge(u, v, w); 31 } 32 int ans = INF, sum = 0; 33 sort(e, e+m); 34 for (int i = 0; i < m; i++){ 35 int a = findset(e[i].u), b = findset(e[i].v); 36 if (a != b){ 37 pa[a] = b; 38 sum++; 39 ans = min(ans, e[i].w); 40 } 41 if (sum == n-1) break; 42 } 43 printf("Case #%d: %d\n", ++kase, ans); 44 } 45 return 0; 46 }
View Code

B. 洗衣

題意:durong有N件衣服要洗,洗衣機一次洗一件衣服,每件衣服只能在固定的一個區間內洗,問需要多少洗衣機

數據範圍:1 <= N <= 1e5, 1 <= st < en <= 1e9

思路1:一道裸貪心,至少大佬們都覺得它裸,原題是POJ3190。挑戰題單上是有這題的,但我拉了沒刷= =。我是真的不會。誒,基礎不牢。

首先為了方便遍歷按開始時間從小到大排序。為了找出正確的貪心策略,先模仿人的思路:對於新拿到的一件衣服,嘗試能不能放在空閑的洗衣機後面,能就更新洗衣機的結束時間,不能就新加洗衣機。

至於實現的方法,用一個優先隊列維護每件衣服的結束時間即可。因為隊列中的元素都是在洗衣機裏的,重載小於號讓結束時間早的優先,如果最早洗衣機的結束時間還晚於當前的開始時間,那就必須新開洗衣機了。

技術分享圖片
 1 #include<cstdio>
 2 #include<queue>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int mx = 1e5+10;
 7 
 8 struct Node{
 9     int s, t;
10     bool operator < (const Node& a) const{
11         return t > a.t || (t == a.t && s > a.s);
12     }
13 }p[mx];
14 
15 bool cmp(Node a, Node b){
16     return a.s < b.s || (a.s == b.s && a.t < b.t);
17 }
18 
19 int main(){
20     int n;
21     while (scanf("%d", &n) == 1){
22         int ans = 1;
23         for (int i = 0; i < n; i++)
24             scanf("%d%d", &p[i].s, &p[i].t);
25         sort(p, p+n, cmp);
26         priority_queue<Node> q;
27         q.push(p[0]);
28         for (int i = 1; i < n; i++){
29             Node u = q.top();
30             if (p[i].s >= u.t) q.pop();
31             else ans++;
32             q.push(p[i]);
33         }
34         printf("%d\n", ans);
35     }
36     return 0;
37 }
View Code

另外不得不說,杜榮菊苣真有錢,洗衣機也多,衣服還有1e5件Σ(?д?lll)

思路2:賽場上不會上面的貪心做法,倒是想到了等價於選擇一個點在盡量多的區間內,需要用洗衣機的數量等於最多的重合區間數量,想到了線段樹的染色問題。那麽就是區間更新+查詢最大值了。不過1e9的數據範圍需要離散化,我還寫得不熟練,比賽時我沒帶線段樹板子,甚至連I題裸的區間更新都忘了,手推線段樹,WA到我不敢寫,這個思路就沒在賽場上實現。補完這種做法以後再附代碼,就當練下離散化了。

CSUST-17級集訓隊選拔賽解題報告