题目描述

You are given a connected weighted graph with $n$ vertices and $m$ edges. The graph doesn’t contain loops nor multiple edges. Consider some edge with id $i$. Let’s determine for this edge the maximum integer weight we can give to it so that it is contained in all minimum spanning trees of the graph if we don’t change the other weights.
You are to determine this maximum weight described above for each edge. You should calculate the answer for each edge independently, it means there can’t be two edges with changed weights at the same time.

代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct line {
long long u, v, c, id; bool mst;
bool operator < (const line &a) const { return c < a.c; }
} l[200001];
struct edge {
long long v, c, id, nxt;
} e[400001];
long long n, m, nume, h[200001], fa[200001], ans[200001];
long long depth[200001], up[200001][20], ma[200001][20], uid[200001];
long long get_fa(long long t) { return t == fa[t] ? t : fa[t] = get_fa(fa[t]); }
void add_edge(long long u, long long v, long long c, long long id) {
e[++nume].v = v, e[nume].c = c, e[nume].id = id, e[nume].nxt = h[u], h[u] = nume;
e[++nume].v = u, e[nume].c = c, e[nume].id = id, e[nume].nxt = h[v], h[v] = nume;
}
void dfs(long long t, long long fa) {
for (int i = h[t]; i; i = e[i].nxt)
if (e[i].v != fa) {
depth[e[i].v] = depth[t] + 1, up[e[i].v][0] = t;
ma[e[i].v][0] = e[i].c, uid[e[i].v] = e[i].id, dfs(e[i].v, t);
}
}
long long get_max(long long u, long long v) {
long long ret = 0;
if (depth[u] < depth[v]) u ^= v ^= u ^= v;
for (int i = 19; i >= 0; --i)
if (depth[u] - depth[v] >= (1 << i))
ret = max(ret, ma[u][i]), u = up[u][i];
if (u == v) return ret;
for (int i = 19; i >= 0; --i)
if (up[u][i] != up[v][i])
ret = max(ret, max(ma[u][i], ma[v][i])), u = up[u][i], v = up[v][i];
return max(ret, max(ma[u][0], ma[v][0]));
}
void update(long long u, long long v, long long val) {
if (depth[u] < depth[v]) u ^= v ^= u ^= v;
long long p = u, q = v;
for (int i = 19; i >= 0; --i)
if (depth[p] - depth[q] >= (1 << i)) p = up[p][i];
if (p != q) {
for (int i = 19; i >= 0; --i)
if (up[p][i] != up[q][i]) p = up[p][i], q = up[q][i];
p = up[p][0];
}
u = get_fa(u), v = get_fa(v);
while (depth[u] > depth[p])
ans[uid[u]] = val - 1, q = get_fa(up[u][0]), fa[u] = q, u = get_fa(u);
while (depth[v] > depth[p])
ans[uid[v]] = val - 1, q = get_fa(up[v][0]), fa[v] = q, v = get_fa(v);
}
int main()
{
cin >> n >> m, memset(ans, -1, sizeof ans);
if (n == m + 1) {
for (int i = 1; i <= m; cout << -1 << ' ', ++i); cout << endl; return 0;
}
for (int i = 1; i <= n; fa[i] = i, ++i);
for (int i = 1; i <= m; cin >> l[i].u >> l[i].v >> l[i].c, l[i].id = i, ++i);
sort(l + 1, l + m + 1);
for (int i = 1; i <= m; ++i) {
long long u = get_fa(l[i].u), v = get_fa(l[i].v);
if (u != v) add_edge(l[i].u, l[i].v, l[i].c, l[i].id), fa[u] = v, l[i].mst = true;
}
depth[1] = 1, dfs(1, 0);
for (int i = 1; i < 20; ++i)
for (int j = 1; j <= n; ++j) {
up[j][i] = up[up[j][i - 1]][i - 1];
ma[j][i] = max(ma[j][i - 1], ma[up[j][i - 1]][i - 1]);
}
for (int i = 1; i <= n; fa[i] = i, ++i);
for (int i = 1; i <= m; ++i)
if (!l[i].mst) {
ans[l[i].id] = get_max(l[i].u, l[i].v) - 1;
update(l[i].u, l[i].v, l[i].c);
}
for (int i = 1; i <= m; cout << ans[i] << ' ', ++i);
cout << endl;
return 0;
}


题目描述

Pavel plays a famous computer game. A player is responsible for a whole country and he can travel there freely, complete quests and earn experience.
This country has $n$ cities connected by $m$ bidirectional roads of different lengths so that it is possible to get from any city to any other one. There are portals in $k$ of these cities. At the beginning of the game all portals are closed. When a player visits a portal city, the portal opens. Strange as it is, one can teleport from an open portal to an open one. The teleportation takes no time and that enables the player to travel quickly between rather remote regions of the country.
At the beginning of the game Pavel is in city number $1$. He wants to open all portals as quickly as possible. How much time will he need for that?

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
long long n, m, k, nume, tot, ans, mi = 1e18;
long long h[100001], p[100001], d[100001], fa[100001], pre[100001];
bool in[100001];
struct edge { long long v, w, nxt; } e[200001];
struct line {
long long u, v, w;
bool operator < (const line &a) const {
return d[u] + w + d[v] < d[a.u] + a.w + d[a.v];
}
} l[200001];
void add_edge(long long u, long long v, long long w) {
e[++nume].v = v, e[nume].w = w, e[nume].nxt = h[u], h[u] = nume;
e[++nume].v = u, e[nume].w = w, e[nume].nxt = h[v], h[v] = nume;
}
void spfa() {
queue<long long> que;
while (!que.empty()) que.pop();
for (int i = 1; i <= n; ++i)
if (!d[i]) in[i] = true, que.push(i);
while (!que.empty()) {
int u = que.front(); in[u] = false, que.pop();
for (int i = h[u]; i; i = e[i].nxt)
if (d[e[i].v] > d[u] + e[i].w) {
d[e[i].v] = d[u] + e[i].w, pre[e[i].v] = pre[u];
if (!in[e[i].v]) in[e[i].v] = true, que.push(e[i].v);
}
}
}
long long get_fa(long long t) {
return t == fa[t] ? t : fa[t] = get_fa(fa[t]);
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; ++i) {
long long u, v, w; cin >> u >> v >> w; add_edge(u, v, w);
}
memset(d, 0x1f, sizeof d), d[1] = 0, spfa(); cin >> k;
for (int i = 1; i <= k; ++i) {
cin >> p[i]; if (d[p[i]] < mi) mi = d[p[i]];
}
ans = mi, memset(d, 0x1f, sizeof d);
for (int i = 1; i <= n; ++i) fa[i] = i, pre[i] = i;
for (int i = 1; i <= k; ++i) d[p[i]] = 0; spfa();
for (int i = 1; i <= n; ++i)
for (int j = h[i]; j; j = e[j].nxt)
l[++tot].u = i, l[tot].v = e[j].v, l[tot].w = e[j].w;
sort(l + 1, l + tot + 1);
for (int i = 1; i <= tot; ++i) {
long long u = get_fa(pre[l[i].u]), v = get_fa(pre[l[i].v]);
if (u != v) fa[u] = v, ans += d[l[i].u] + l[i].w + d[l[i].v];
}
cout << ans << endl;
return 0;
}


题目描述

You are given an array $a$ consisting of $n$ elements. The imbalance value of some subsegment of this array is the difference between the maximum and minimum element from this segment. The imbalance value of the array is the sum of imbalance values of all subsegments of this array.
For example, the imbalance value of array $[1, 4, 1]$ is $9$, because there are $6$ different subsegments of this array:

• $[1]$ (from index $1$ to index $1$), imbalance value is $0$;
• $[1, 4]$ (from index $1$ to index $2$), imbalance value is $3$;
• $[1, 4, 1]$ (from index $1$ to index $3$), imbalance value is $3$;
• $[4]$ (from index $2$ to index $2$), imbalance value is $0$;
• $[4, 1]$ (from index $2$ to index $3$), imbalance value is $3$;
• $[1]$ (from index $3$ to index $3$), imbalance value is $0$.

You have to determine the imbalance value of the array $a$.

题意概述

$$\sum_{1 \le i \le j \le n} (max_{i, j}-min_{i, j})$$

代码1

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct number {
long long num, id, rec;
} a[1000001];
bool cmp(number a, number b) {return a.num < b.num;}
long long n, fa[1000002], s[1000002], ans;
int get_fa(long long t) {
return t == fa[t] || fa[t] == 0 ? fa[t] : fa[t] = get_fa(fa[t]);
}
void process(int t) {
int i, j;
if (t == 1) i = 1, j = n + 1;
else i = n, j = 0;
for (; i != j; i += t) {
fa[a[i].id] = a[i].id;
s[a[i].id] = 1;
long long p = get_fa(a[i].id - 1), q = get_fa(a[i].id + 1);
a[i].rec = (s[p] + 1) * (s[q] + 1);
if (s[p]) {
s[p] += s[get_fa(a[i].id)];
fa[get_fa(a[i].id)] = p;
}
if (s[q]) {
s[q] += s[get_fa(a[i].id)];
fa[get_fa(a[i].id)] = q;
}
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i].num;
a[i].id = i;
}
sort(a + 1, a + n + 1, cmp);
process(1);
for (int i = 1; i <= n; ++i) {
ans += a[i].num * a[i].rec;
}
memset(fa, 0, sizeof(fa));
memset(s, 0, sizeof(s));
process(-1);
for (int i = 1; i <= n; ++i) {
ans -= a[i].num * a[i].rec;
}
cout << ans << endl;
return 0;
}


代码2

#include <iostream>
using namespace std;
long long n, a[1000001], l[1000001], r[1000001], ans;
void process(int t) {
for (int i = 1; i <= n; ++i) {
l[i] = r[i] = i;
}
for (int i = 2; i <= n; ++i) {
int now = i;
while (now > 1 && a[i] * t >= a[now - 1] * t) now = l[now - 1];
l[i] = now;
}
for (int i = n - 1; i; --i) {
int now = i;
while (now < n && a[i] * t > a[now + 1] * t) now = r[now + 1];
r[i] = now;
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
process(1);
for (int i = 1; i <= n; ++i) {
ans += a[i] * (i - l[i] + 1) * (r[i] - i + 1);
}
process(-1);
for (int i = 1; i <= n; ++i) {
ans -= a[i] * (i - l[i] + 1) * (r[i] - i + 1);
}
cout << ans << endl;
return 0;
}