A - Cut
- 題意:
將陣列的後k個字元移到前面 - 思路:
- 可以用rotate()函式讓陣列中的元素滾動旋轉
rotate(v.begin(), v.begin() + n - k, v.end());
- 直接輸出後k個元素,再輸出前n-k個元素
for(int i=n-k;i<n;i++) write(v[i]); for(int i=0;i<n-k;i++) write(v[i]);
- 可以用rotate()函式讓陣列中的元素滾動旋轉
B - Decrease 2 max elements
- 題意:
每次令陣列中最大的兩個數-1,求多少次操作後只剩下一個數 - 思路:
注意到 2≤N≤100 , 1<=A[i]<=100
兩眼一閉就是寫,直接就上priority_queue,不帶半點智慧和思考,題幹怎麼說就怎麼寫,怎麼簡單怎麼來void solve() { priority_queue<int> q; int n = read(); for(int i=0;i<n;i++) q.push(read()); int cnt = 0; while(q.size()>1){ int t1 = q.top(); q.pop(); int t2 = 1; if(q.size()) t2 = q.top(); q.pop(); if(t1 - 1) q.push(t1-1); if(t2 - 1) q.push(t2-1); cnt++; } cout<<cnt<<endl; }
C - Triple Attack
- 題意:
從前往後遍歷陣列A, 每次操作 T+=1, T%3!=0 的時候 A[i]-=1, T%3==0 的時候 A[i]-=3; - 思路:
每輪 T += 3, A[i] -= 5 , 所以當 T%3==0 的時候直接將 A[i] 減到5以下,再逐次操作
code:int n = read(); vector<int> v; for(int i = 0; i < n; i++) v.push_back(read()); int t = 1; for(int i=0; i < n; i++){ while(v[i]>0){ if(t%3==0 && v[i]>0) v[i]-=3,t++; else if(t%3!=0 && v[i]>0) v[i]-=1,t++; if(t%3==0 && t>=3 && v[i]>=5) t+=v[i]/5*3,v[i]%=5; } } cout<<t-1<<endl;
D - Minimum Steiner Tree
- 題意:
給一個樹,再給一些關鍵節點,求如果要保留這些關鍵節點則至少應該保留哪些節點 - 思路:
顯然給出的關鍵節點必須保留,考慮到是樹可以用dfs,而因為關鍵節點必須保留所以可以任意選一個關鍵節點當作根
從根往深處搜尋,如果該節點為關鍵節點則該節點必然需要保留,標記此節點;
如果該節點往下的任一 一節點為關鍵節點,該節點同樣不可或缺,標記節點;
可以根據dfs的返回值知道該節點往下的分支是否包含關鍵節點。int n, k; vector<vector<int>> e; unordered_map<int,int> mp,st,vis; int dfs(int x){ int ret = 0; vis[x] = 1; //記憶化搜尋,搜過的就不再搜了 for(auto it:e[x]){ if(!vis[it]){ ret |= dfs(it); //按位與,如果返回值有1則ret為1 } } if(mp[x]) ret = 1; if(ret) st[x] = 1; return ret; } void solve() { n = read(), k = read(); e.resize(n+1); for(int i=1;i<n;i++){ int u = read(), v = read(); e[u].push_back(v); e[v].push_back(u); } int ed = 0; for(int i=0;i<k;i++){ ed = read(); mp[ed] = 1; //記錄該節點為關鍵節點 } dfs(ed); int ans = 0; for(auto it:st){ if(it.se) ans++; } cout<<ans<<endl; }