比賽地址ios
題目連接
⭐c++
題目:
給出一個數組\(a\)並能進行一個操做使得數組元素更改成數組任意其餘兩元素之和,問是否可讓數組元素所有小於等於\(d\)數組
解析:
排序後判斷最大值是否小於等於\(d\)或者最小的兩個值是否小於等於\(d\)便可優化
#include<bits/stdc++.h> using namespace std; const int maxn = 105; int n, dat[maxn]; int main() { int T; scanf("%d", &T); while (T--) { int n, d; dat[1] = 0; scanf("%d%d", &n, &d); for (int i = 0; i < n; ++i) scanf("%d", &dat[i]); sort(dat, dat + n); printf("%s\n", dat[n - 1] <= d || dat[0] + dat[1] <= d ? "YES" : "NO"); } }
題目連接
⭐spa
題目:
給出兩個字符串,定義\(LCM(S_1,S_2)\)是由這兩個串做爲循環節的最小長度串,問\(LCM(S_1,S_2)\)是什麼,若是不存在則輸出\(-1\)code
解析:
若是\(LCM\)存在,則它的長度必定是\(LCM(len_1,len_2)\),那麼已知最終串的長度,就能夠算出每一個循環節的循環次數,判斷循環倍增後的串是否相同便可排序
#include<bits/stdc++.h> using namespace std; string str[2]; string repeat(const string& a, int x) { string t; while (x--) t += a; return t; } int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } int main() { ios::sync_with_stdio(false); cin.tie(0); int T; cin >> T; while (T--) { cin >> str[0] >> str[1]; int d = gcd(str[0].length(), str[1].length()); string t[2] = { repeat(str[0],str[1].length() / d),repeat(str[1],str[0].length() / d) }; cout << (t[0] == t[1] ? t[0] : "-1") << endl; } }
題目連接
⭐⭐索引
題目:
給出\(n\)與\(k\),以及對應的數組\(a=1,2,\dots,k-1,k,k-1,k-2,\dots,k-(n-k)\),如今假定有一個長度爲\(k\)的排列\(p\),依照他構造出數組\(b\),使得\(b[i]=p[a[i]]\),問使得\(b\)中逆序對數不超過\(a\)的話,p中知足要求的且爲最大字典序的排列是什麼ci
解析:
這樣的變換能夠理解爲\(a\)爲索引下表,\(b\)爲對應值
o( ̄▽ ̄)ブ找規律能夠發現,將本來\(k,k-1,k-2,\dots,k-(n-k)\)進行倒序排列,逆序對數不會改變,且可讓字典序增長,但除此以外的序列仍然須要服從正序排列\(1\dots n-(n-k+1)\)字符串
#include<bits/stdc++.h> using namespace std; int n, k; int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &k); int a = n - k; int b = k - a; for (int i = 1; i < b; ++i) printf("%d ", i); for (int j = 0; j <= a; ++j) printf("%d ", k - j); printf("\n"); } }
題目連接
⭐⭐
題目:
給出一系列操做「+1」「-1」,以及\(q\)次查詢,每次查詢區間\([l,r]\)內的操做忽略,那麼打印出整個操做序列中出現的不一樣數值的個數
解析:
注:
這道題用\(st\)表,線段樹也能夠,可是更浪費時間,由於這道題只須要得到兩端的極值,且對於求取後半段極值的方法,也不必定必須用\(dp\),也能夠直接從後向前遍歷找到加上以前操做的影響得到的極值,使用時減去影響便可(即\(eh[r+1]-sum[r]\)),兩種求解都是\(O(n)\)處理
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5 + 5; int sh[maxn], sl[maxn], sum[maxn], eh[maxn], el[maxn]; char op[maxn]; int main() { int t, n, m; scanf("%d", &t); while (t--) { scanf("%d%d%s", &n, &m, op + 1); for (int i = 1; i <= n; i++) { if (op[i] == '+') sum[i] = sum[i - 1] + 1; else sum[i] = sum[i - 1] - 1; sh[i] = max(sh[i - 1], sum[i]); sl[i] = min(sl[i - 1], sum[i]); } eh[n + 1] = el[n + 1] = 0; for (int i = n; i >= 1; i--) { if (op[i] == '+') { eh[i] = eh[i + 1] + 1; el[i] = el[i + 1] == 0 ? 0 : el[i + 1] + 1; } else { eh[i] = eh[i + 1] == 0 ? 0 : eh[i + 1] - 1; //也能夠寫做eh[i]=max(eh[i+1]-1,0) el[i] = el[i + 1] - 1; } } int l, r; while (m--) { scanf("%d%d", &l, &r); int low = min(sl[l - 1], sum[l - 1] + el[r + 1]), high = max(sh[l - 1], sum[l - 1] + eh[r + 1]); printf("%d\n", high - low + 1); } } return 0; }
題目連接
⭐⭐⭐⭐
題目:
給出一張圖,定義\((u,v)\)的路徑權值=路徑權重之和+路徑中最小的權重-路徑中最大的權重,求\(1\)到各點的路徑權值最小值
解析:
同時每一個轉移方程能夠類比dijkstra,使用堆優化,尋找當前最短路徑,保證每次能夠肯定一個最終狀態
3. 最終答案輸出狀態3對應的值便可
注意:
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define MEM(X,Y) memset(X,Y,sizeof(X)) typedef long long LL; using namespace std; /*===========================================*/ const int maxn = 2e5 + 5; struct Edge { int to; LL w; }; struct Node { int st, p; LL w; }; queue<Node> q; vector<Edge> e[maxn]; LL dis[maxn][4]; void add(int u, int v, int w) { e[u].push_back(Edge{ v,w }); e[v].push_back(Edge{ u,w }); } void dij() { dis[1][0] = 0; q.push(Node{ 0,1,0 }); while (!q.empty()) { auto t = q.front(); q.pop(); if (dis[t.p][t.st] != t.w) continue; for (auto& i : e[t.p]) { if (dis[t.p][t.st] + i.w < dis[i.to][t.st]) { dis[i.to][t.st] = dis[t.p][t.st] + i.w; q.push(Node{ t.st,i.to ,dis[i.to][t.st] }); } if (!(t.st & 1) && dis[t.p][t.st] < dis[i.to][t.st | 1]) { dis[i.to][t.st | 1] = dis[t.p][t.st]; q.push(Node{ t.st | 1,i.to,dis[i.to][t.st | 1] }); } if (!(t.st & 2) && dis[t.p][t.st] + 2 * i.w < dis[i.to][t.st | 2]) { dis[i.to][t.st | 2] = dis[t.p][t.st] + 2 * i.w; q.push(Node{ t.st | 2,i.to,dis[i.to][t.st | 2] }); } } } } int main() { MEM(dis, INF); int n, m; int a, b, c; scanf("%d%d", &n, &m); while (m--) { scanf("%d%d%d", &a, &b, &c); add(a, b, c); if (a > b) swap(a, b); if (a == 1) dis[b][3] = c; } dij(); for (int i = 2; i <= n; ++i) printf("%lld ", dis[i][3]); }