比赛地址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(); }