p1. 成績指標
我們定義分數
我們將其排序並從
如果
如果
程式碼
#include <bits/stdc++.h>
using namespace std;
vector<int> m;
int main(){
int n, minX = INT_MAX, maxY = INT_MIN;
cin >> n;
m.resize(n);
for (auto &e: m){
cin >> e;
if (e >= 60)
minX = min(minX, e);
else
maxY = max(maxY, e);
}
sort(m.begin(), m.end());
for (auto i: m)
cout << i << ' ';
cout << '\n';
if (minX == INT_MAX)
cout << maxY << '\n' << "worst case";
else if (maxY == INT_MIN)
cout << "best case" << '\n' << minX;
else
cout << maxY << '\n' << minX << '\n';
}
p2. 矩陣轉換
題目連結
定義
//值 座標(i, j)
1(0, 0), 1(0, 1)
1(1, 0), 3(1, 1)
2(2, 0), 1(2, 1)
翻轉後
2(0, 0), 1(0, 1)
1(1, 0), 3(1, 1)
1(2, 0), 1(2, 1)
旋轉後得
1(0, 0) 1(0, 1) 2(0, 2)
1(1, 0) 3(1, 1) 1(1, 2)
透過觀察位置的變化就會發現其規律。
- 翻轉及其反操作
經過翻轉 座標變化 ->
Note:
這裡的操作次數為因為每次執行會交換到兩條行數
- 旋轉及其反操作
經過旋轉 座標變化 ->
Note
這裡的參數已經變為控制列的 參數
因此要將兩者的值調換,避免與 變成了錯誤的行列數
因題目要求因此實作時記得將操作改為反操作的形式
程式碼
#include <bits/stdc++.h>
using namespace std;
int arr[10][10], r, c, m, ops;
void flip_back(){
for (int i = 0; i < r/2; i++)
for (int j = 0; j < c; j++)
swap(arr[i][j], arr[r-i-1][j]);
}
void rotate_back(){
int tmp[10][10];
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
tmp[i][j] = arr[i][j];
swap(r, c);
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
arr[i][j] = tmp[j][r-i-1];
}
int main(){
cin >> r >> c >> m;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cin >> arr[i][j];
}
}
while (m--) {
cin >> ops;
if (ops)
flip_back();
else
rotate_back();
}
cout << r << ' ' << c << '\n';
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++)
cout << arr[i][j] << ((j+1 == c)? "":" ");
cout << '\n';
}
}
p3. 線段覆蓋長度
這題我們用貪心的角度去思考,如果將線段按左界排序,我們就可以逐步判斷線段覆蓋的區間。
我們定義當前最大左右界為
因為排序的關係所以我們可以保證新加入的線段
- 如果新加入的線段
,那麼覆蓋長度則不變 - 如果新加入的線段
,那麼代表說 這個區間已經被覆蓋了,因此我們只需要新增未被覆蓋的區間 - 如果新加入的線段
,那麼代表說 這塊是完全獨立的線段,我們只需新增它即可
實作時記得每次都要更新當前最大右界
複雜度:
#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define l first
#define r second
priority_queue<pii, vector<pii>, greater<pii>> pq;
int main(){
int n, a, b;
cin >> n;
while (n--){
cin >> a >> b;
pq.push({a, b});
}
int mr = -1, result = 0;
while (pq.size()) {
pii t = pq.top();
pq.pop();
if (t.r <= mr)
continue;
result += (t.l <= mr)? (t.r - mr): (t.r - t.l);
mr = t.r;
}
cout << result << '\n';
}
p4. 血緣關係
這題算是圖論的經典題,問你圖上距離最遠的兩個點,即為所謂的樹直徑。
由於只有詢問一次,所以只要做兩次 Depth-First-Search 就行。
至於 DFS 的實作這裡就不多作介紹。
- 第一次 DFS 的時候先搜尋離當前節點最遠的節點。
- 第二次 DFS 的時候以第一次搜尋到的點作為起點搜尋最遠的節點。
複雜度:
程式碼
#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> g;
int md = -1, mi = -1;
void dfs(int idx, int father, int depth){
for (auto i: g[idx]){
if (i != father){
dfs(i, idx, depth+1);
}
}
if (depth > md){
md = depth;
mi = idx;
}
}
signed main(){
int n, a, b;
cin >> n;
g.assign(n, {});
for (int i = 1; i < n; i++){
cin >> a >> b;
g[a].pb(b);
g[b].pb(a);
}
dfs(0, -1, 0);
dfs(mi, -1, 0);
cout << md << '\n';
}