CSUST-17級集訓隊選拔賽解題報告
摸了一個寒假的魚,賽前各種被奶,就感覺自己要涼,我的感覺向來是對的,結果真的涼透了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> 2View Code#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 }
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級集訓隊選拔賽解題報告