比赛链接:ABC395
按照题意模拟
#include
using namespace std;
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
bool flag = true;
for (int i = 1; i < n; i++)
if (a[i] <= a[i - 1]) {
flag = false;
break;
}
if (flag) cout << "Yes" << endl;
else cout << "No" << endl;
return 0;
}
按照题意模拟
#include
using namespace std;
char s[55][55];
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
int j = n - i + 1;
if (i <= j) {
char c;
if (i & 1) c = '#';
else c = '.';
for (int x = i; x <= j; x++)
for (int y = i; y <= j; y++) s[x][y] = c;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cout << s[i][j];
}
cout << endl;
}
return 0;
}
对于每一个相同的 a a a 的值,记录他们的下标,答案是相距最近的两个相同的 a a a 值的距离
时间复杂度: O ( N + A ) O(N + A) O(N+A)( A A A 代表 A i A_i Ai 的最大值)。
#include
using namespace std;
const int N = 2e5 + 10;
int n, a[N], maxm = 0;
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
maxm = max(a[i], maxm);
}
vector<vector<int>> vis(maxm + 1);
for (int i = 1; i <= n; i++) vis[a[i]].push_back(i);
int ans = INT_MAX;
for (int i = 1; i <= maxm; i++) {
if (vis[i].size() >= 2) {
for (int j = 1; j < vis[i].size(); j++)
ans = min(ans, vis[i][j] - vis[i][j - 1] + 1);
}
}
if (ans != INT_MAX) cout << ans << endl;
else cout << -1 << endl;
return 0;
}
在这样的情况下,
时间复杂度: O ( N + Q ) O(N + Q) O(N+Q)。
#include
using namespace std;
const int N = 1e6 + 10;
int n, q, f[N], pos[N], idx[N];
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> q;
for (int i = 1; i <= n; i++) f[i] = pos[i] = idx[i] = i;
while (q--) {
int op, a, b;
cin >> op;
if (op == 1) {
cin >> a >> b;
f[a] = idx[b];
}
if (op == 2) {
cin >> a >> b;
swap(pos[idx[a]], pos[idx[b]]);
swap(idx[a], idx[b]);
}
if (op == 3) {
cin >> a;
cout << pos[f[a]] << '\n';
}
}
return 0;
}
对于每一对给出的 ( u , v ) (u, v) (u,v),直接连一条有向边,权值为 1 1 1。
为了表示翻转操作,可以给 ( v + n , u + n ) (v + n, u + n) (v+n,u+n) 连一条边,权值为 1 1 1,并且对于 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n,连 ( i , i + n ) (i, i + n) (i,i+n) 跟 ( i + n , i ) (i + n, i) (i+n,i) 两条边,权值都设为 x x x。
接着,直接从 1 1 1 号节点开始跑 d i j s k t r a dijsktra dijsktra,最后的答案为 min ( d i s n , d i s 2 n ) \min(dis_n, dis_{2n}) min(disn,dis2n)。
时间复杂度: O ( n log n ) O(n\log n) O(nlogn)
#include
using namespace std;
#define int long long
const int N = 2e5 + 10, M = N << 3;
int n, m, x, head[N << 1], num = 0, dis[N << 1], vis[N << 1] = { 0 };
struct edge { int to, nxt, w; } e[M];
struct node {
int u, d;
bool operator< (const node &curNode) const {
return curNode.d < d;
}
};
void addEdge(int u, int v, int w) { e[++num] = (edge){ v, head[u], w}, head[u] = num; }
void dijsktra(int s) {
for (int i = 1; i <= 2 * n; i++) dis[i] = LLONG_MAX;
dis[s] = 0;
priority_queue<node> q;
q.push({s, 0});
while (!q.empty()) {
int u = q.top().u; q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to, w = e[i].w;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.push({v, dis[v]});
}
}
}
}
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> m >> x;
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
addEdge(u, v, 1), addEdge(v + n, u + n, 1);
}
for (int i = 1; i <= n; i++) addEdge(i, i + n, x), addEdge(i + n, i, x);
dijsktra(1);
cout << min(dis[n], dis[2 * n]) << endl;
return 0;
}
可以发现 H H H 满足单调性( H H H 越大花费越少),我们可以二分 H H H,然后 O ( n ) O(n) O(n) 检查是不是符合条件。
检查实现:
时间复杂度: O ( N log ( U i + D i ) ) O(N \log(U_i + D_i)) O(Nlog(Ui+Di))。
#include
using namespace std;
#define int long long
const int N = 2e5 + 10;
int n, x, u[N], d[N];
bool check(int mid) {
int l = LLONG_MIN, r = LLONG_MAX;
for (int i = 1; i <= n; i++) {
l = max(l, max(0LL, mid - d[i])), r = min(r, u[i]);
if (l > r) return false;
l -= x, r += x;
}
return true;
}
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> x;
int l = 0LL, r = LLONG_MAX, tar = 0LL;
for (int i = 1; i <= n; i++) cin >> u[i] >> d[i], r = min(r, u[i] + d[i]);
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) l = mid + 1, tar = mid;
else r = mid - 1;
}
int ans = 0LL;
for (int i = 1; i <= n; i++) ans += u[i] + d[i] - tar;
cout << ans << endl;
return 0;
}