比賽地址node
題目連接
⭐c++
題目:
給出\(n\)堆磚塊,容許將第\(i\)堆磚塊向\(i+1\)堆移動任意塊,則詢問所給磚塊序列能否構成一個單調遞增的序列數組
解析:
所給操做容許將前\(i\)個磚塊以任意形式擺放,因此只須要當前磚塊總數知足遞增序列的最小要求便可spa
#include<bits/stdc++.h> int main() { int T; int n; scanf("%d", &T); while (T--) { scanf("%d", &n); long long now = 0, cnt = 0, re = 0; int t; bool ok = true; while (n--) { scanf("%d", &t); now += t; if (!ok) continue; if (re > now) ok = false; re += ++cnt; } printf("%s\n", ok ? "YES" : "NO"); } }
題目連接
⭐code
題目:
給出一組點的座標,求出知足曼哈頓距離最小的點的個數排序
解析:
儘管是二維座標,其實能夠與一維座標問題的求解是同樣得,先將數組排序,考慮到某點到任意兩點的距離爲\(d=|x_1-x|+|x_2-x|\),在兩點之間取得最小值,因此能夠每次向兩端取點,這樣最後最小值就落在了中位數
若是是奇數則只有1種取法,偶數則爲中位數的距離,乘法原理處理二維問題便可get
#include<bits/stdc++.h> using namespace std; const int maxn = 1e3 + 5; long long x[maxn], y[maxn]; int main() { int T; int n; scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%lld%lld", &x[i], &y[i]); if (n & 1) { printf("1\n"); continue; } sort(x, x + n); sort(y, y + n); printf("%lld\n", (x[n / 2] - x[n / 2 - 1] + 1) * (y[n / 2] - y[n / 2 - 1] + 1)); } }
題目連接
⭐⭐it
題目:
給出數組長度\(n\), 最多進行不超過20次詢問,每次詢問\(l,r\),給出\([l,r]\)第二大值的座標,求出最大值的位置io
解析:class
注意:
若是\(p\)出如今1的位置,則不須要進行第二次詢問,\(MAX\in[2,n]\)是確定的,不然會出現[1,1]的詢問錯誤
#include<bits/stdc++.h> using namespace std; const int maxn = 1e3 + 5; long long x[maxn], y[maxn]; bool ok; int main() { int n; scanf("%d", &n); int sec; printf("? 1 %d\n\n", n); fflush(stdout); scanf("%d", &sec); int mid; int t; int l, r; if (sec != 1) { printf("? 1 %d\n\n", sec); fflush(stdout); scanf("%d", &t); } if (sec == 1 || sec != t) { l = sec + 1, r = n; while (r != l) { mid = l + (r - l) / 2; printf("? %d %d\n\n", sec, mid); fflush(stdout); scanf("%d", &t); if (t == sec) r = mid; else l = mid + 1; } } else { l = 1, r = sec - 1; while (r != l) { mid = l + (r - l + 1) / 2; printf("? %d %d\n\n", mid, sec); fflush(stdout); scanf("%d", &t); if (t == sec) l = mid; else r = mid - 1; } } printf("! %d", l); }
題目連接
⭐⭐⭐
題目:
給出\(n,k\),以及一個長度爲\(n\)的數組,求出一個長度至少爲\(k\)的連續子序列值在排序後的中位數最大值
解析:
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5 + 5; int dat[maxn]; int sum[maxn]; int n, k; bool check(int x) { int mn = 0x3f3f3f3f, mx = -mn; for (int i = 1; i <= n; ++i) { sum[i] = sum[i - 1] + (dat[i] >= x ? 1 : -1); if (i >= k) mn = min(sum[i - k], mn), mx = max(sum[i] - mn, mx); } return mx > 0; } int main() { scanf("%d%d", &n, &k); for (int i = 1; i <= n; ++i) scanf("%d", &dat[i]); int l = 1, r = n, mid; while (l < r) { mid = l + (r - l + 1) / 2; if (check(mid)) l = mid; else r = mid - 1; } printf("%d", l); }
題目連接
⭐⭐⭐⭐
題目:
給出一幅圖,要求一次必須走兩端路,且費用爲兩端路之和的平方,問從\(1\)點出發到各點的最小費用
解析:
因爲必須走兩端路,所以能夠將路分爲兩段,其中前半段能夠從任意點出發得到,後半段必須從中間點出發得到
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; typedef pair<int, int> P; vector<P> e[maxn]; int dis[maxn][51], dis2[maxn]; int n, m; void addedge(int u, int v, int w) { e[u].push_back(P(v, w)); } struct T { int st, pre, pw, c; bool operator<(const T& a)const { return c > a.c; } }; void dij() { priority_queue<T> q; memset(dis, 0x3f3f3f3f, sizeof(dis)); memset(dis2, 0x3f3f3f3f, sizeof(dis2)); dis2[1] = 0; q.push(T{ 0,1,0,0 }); while (!q.empty()) { auto t = q.top(); q.pop(); if (t.st) { if (dis[t.pre][t.pw] < t.c) continue; for (auto& i : e[t.pre]) { if (dis2[i.first] > t.c + 2 * t.pw * i.second + i.second * i.second) { dis2[i.first] = t.c + 2 * t.pw * i.second + i.second * i.second; q.push(T{ 0,i.first,0,dis2[i.first] }); } } } else { if (dis2[t.pre] < t.c) continue; for (auto& i : e[t.pre]) { if (dis[i.first][i.second] > t.c + i.second * i.second) { dis[i.first][i.second] = t.c + i.second * i.second; q.push(T{ 1,i.first,i.second,dis[i.first][i.second] }); } } } } for (int i = 1; i <= n; ++i) if (dis2[i] == 0x3f3f3f3f) printf("-1 "); else printf("%d ", dis2[i]); } int main() { int a, b, c; scanf("%d%d", &n, &m); while (m--) { scanf("%d%d%d", &a, &b, &c); addedge(a, b, c), addedge(b, a, c); } dij(); }
注意:
開大數組範圍
#include<bits/stdc++.h> using namespace std; const int maxn = 6e6 + 5; typedef pair<int, int> P; vector<P> e[maxn]; int dis[maxn]; int n, m; void addedge(int u, int v, int w) { e[u * 51].push_back(P(v * 51 + w, 0)); for (int i = 1; i <= 50; ++i) e[u * 51 + i].push_back(P(v * 51, (w + i) * (w + i))); } void dij() { priority_queue<P, vector<P>, greater<P>> q; memset(dis, 0x3f3f3f3f, sizeof(dis)); dis[0] = 0; q.push(P(0, 0)); while (!q.empty()) { auto t = q.top(); q.pop(); if (dis[t.second] < t.first) continue; for (auto& i : e[t.second]) { if (dis[i.first] > dis[t.second] + i.second) { dis[i.first] = dis[t.second] + i.second; q.push(P(dis[i.first], i.first)); } } } for (int i = 0; i < n; ++i) if (dis[i * 51] == 0x3f3f3f3f) printf("-1 "); else printf("%d ", dis[i * 51]); } int main() { int a, b, c; scanf("%d%d", &n, &m); while (m--) { scanf("%d%d%d", &a, &b, &c); --a, --b; addedge(a, b, c), addedge(b, a, c); } dij(); }