A. Sorting by Subsequences
暴力。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 100005;
int a[MAXN], l[MAXN], n, m;
vector <int> ans[MAXN];
bool v[MAXN];
inline void Dfs(int x)
{
if (v[x])
return ;
v[x] = 1; ans[m].pb(x);
Dfs(a[x]);
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read();
for (int i = 1; i <= n; i ++)
a[i] = l[i] = Read();
sort(l + 1, l + n + 1);
for (int i = 1; i <= n; i ++)
a[i] = lower_bound(l + 1, l + n + 1, a[i]) - l;
for (int i = 1; i <= n; i ++)
if (!v[i])
m ++, Dfs(i);
printf("%d\n", m);
for (int i = 1; i <= m; i ++)
{
printf("%d", ans[i].size());
for (auto x : ans[i])
printf(" %d", x);
putchar(10);
}
}
B. Interactive LowerBound
随机化。
考虑先随机取1000个,然后从最大的小于x的那个开始暴力跳,正确性算算是对的。
include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 50005;
int n, s, x, val[MAXN], nxt[MAXN], p[MAXN], cv = -1, cp;
inline int Query(int x)
{
printf("? %d\n", x);
fflush(stdout);
val[x] = Read(), nxt[x] = Read();
}
inline void Print(int x)
{
printf("! %d\n", x);
fflush(stdout);
exit(0);
}
int main()
{
#ifdef wxh010910
//freopen("data.in", "r", stdin);
#endif
srand(time(0));
n = Read(), s = Read(), x = Read();
for (int i = 1; i <= n; i ++)
p[i] = i;
random_shuffle(p + 1, p + n + 1);
for (int i = 1; i <= n; i ++)
if (p[i] == s)
swap(p[i], p[1]);
for (int i = 1; i <= min(n, 1000); i ++)
{
Query(p[i]);
if (val[p[i]] < x && val[p[i]] > cv)
cv = val[p[i]], cp = p[i];
}
if (!cp)
Print(val[s]);
while (true)
{
if (!~nxt[cp])
Print(-1);
cp = nxt[cp];
Query(cp);
if (val[cp] >= x)
Print(val[cp]);
}
return 0;
}
C. Upgrading Tree
那个限制提示我们找重心。
以重心为根构造一下发现可以调整到所有点深度不超过
两个重心就分开算就好了。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 200005;
int par[MAXN], siz[MAXN], st[MAXN], dep[MAXN], tp, n;
vector <int> adj[MAXN], c[MAXN], r;
vector <pair <int, pii>> ans;
inline void Dfs(int x, int p)
{
bool f = 1;
siz[x] = 1;
for (auto y : adj[x])
if (y ^ p)
{
Dfs(y, x), siz[x] += siz[y];
if (siz[y] > n >> 1)
f = 0;
}
if (n - siz[x] > n >> 1)
f = 0;
if (f)
r.pb(x);
}
inline void Dfs2(int x, int p)
{
par[st[tp ++] = x] = p;
if (dep[x] >= 3)
c[st[1]].pb(x);
for (auto y : adj[x])
if (y ^ p)
dep[y] = dep[x] + 1, Dfs2(y, x);
tp --;
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read();
for (int i = 1, x, y; i < n; i ++)
x = Read(), y = Read(), adj[x].pb(y), adj[y].pb(x);
Dfs(1, 0);
if (r.size() == 1)
Dfs2(r[0], 0);
else
Dfs2(r[0], r[1]), Dfs2(r[1], r[0]);
for (int i = 1; i <= n; i ++)
if (c[i].size())
{
int cur = i;
for (auto x : c[i])
ans.pb(mp(par[i], mp(cur, x))), ans.pb(mp(x, mp(par[x], i))), cur = x;
ans.pb(mp(par[i], mp(cur, i)));
}
printf("%d\n", ans.size());
for (auto x : ans)
printf("%d %d %d\n", x.xx, x.yy.xx, x.yy.yy);
}
D. Dynamic Shortest Path
这是个暴力题…时限有毒…
考虑先跑一遍最短路,由于每次操作只会把边权增加1,所以记
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 100005;
int n, m, Q, mx, hed[MAXN], p[MAXN], v[MAXN], w[MAXN], f[MAXN];
vector <int> d[MAXN];
LL dis[MAXN], INF;
bool vis[MAXN];
inline void Dijkstra()
{
priority_queue <pair <LL, int>, vector <pair <LL, int>>, greater <pair <LL, int>>> q;
mset(dis, 0x3f); INF = dis[0];
dis[1] = 0; q.push(mp(0, 1));
while (!q.empty())
{
int x = q.top().yy; q.pop();
if (vis[x])
continue;
vis[x] = 1;
for (int i = hed[x]; i; i = v[i])
if (dis[p[i]] > dis[x] + w[i])
dis[p[i]] = dis[x] + w[i], q.push(mp(dis[p[i]], p[i]));
}
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read(), m = Read(), Q = Read();
for (int i = 1, x, y; i <= m; i ++)
x = Read(), y = Read(), w[i] = Read(), p[i] = y, v[i] = hed[x], hed[x] = i;
Dijkstra();
while (Q --)
if (Read() == 1)
{
int x = Read();
if (dis[x] >= INF)
puts("-1");
else
printf("%I64d\n", dis[x]);
}
else
{
for (int x = Read(); x; x --)
w[Read()] ++;
mset(f, 0x3f);
mx = f[1] = 0; d[0].pb(1);
for (int i = 0; i <= mx; i ++)
for (int j = 0; j < d[i].size(); j ++)
{
int x = d[i][j];
if (i > f[x])
continue;
for (int k = hed[x]; k; k = v[k])
if (f[p[k]] > f[x] + dis[x] + w[k] - dis[p[k]])
{
f[p[k]] = f[x] + dis[x] + w[k] - dis[p[k]];
if (f[p[k]] <= n)
d[f[p[k]]].pb(p[k]), mx = max(mx, f[p[k]]);
}
}
for (int i = 0; i <= mx; i ++)
d[i].clear();
for (int i = 1; i <= n; i ++)
if (dis[i] < INF)
dis[i] += f[i];
}
return 0;
}
E. Maximum Flow
你发现那个东西就是要求一个最小割。
对于u到
然后随便跑个上下界网络流就行了。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 105;
const int MAXM = 10005;
const int INF = 0x3f3f3f3f;
namespace Flow
{
struct Edge
{
int p, v, w;
} e[MAXM];
int e_cnt, S, T, V, ql, qr, q[MAXN], hed[MAXN], dis[MAXN], cur[MAXN];
inline void Init(int n)
{
V = n;
for (int i = 0; i < V; i ++)
hed[i] = 0;
e_cnt = 1;
}
inline void Addedge(int x, int y, int w)
{
e[++ e_cnt] = {y, hed[x], w}; hed[x] = e_cnt;
e[++ e_cnt] = {x, hed[y], 0}; hed[y] = e_cnt;
}
inline bool Bfs()
{
for (int i = 0; i < V; i ++)
dis[i] = 0;
dis[q[ql = 0] = S] = qr = 1;
while (ql ^ qr)
{
int x = q[ql ++];
for (int i = hed[x]; i; i = e[i].v)
if (e[i].w && !dis[e[i].p])
dis[q[qr ++] = e[i].p] = dis[x] + 1;
}
return dis[T];
}
inline int Dfs(int x, int f)
{
if (x == T)
return f;
int ret = 0, t = 0;
for (int &i = cur[x]; i; i = e[i].v)
if (e[i].w && dis[e[i].p] == dis[x] + 1)
{
t = Dfs(e[i].p, min(f, e[i].w));
f -= t; ret += t; e[i].w -= t; e[i ^ 1].w += t;
if (!f)
return ret;
}
return dis[x] = -1, ret;
}
inline int Dinic()
{
int ret = 0;
while (Bfs())
{
for (int i = 0; i < V; i ++)
cur[i] = hed[i];
ret += Dfs(S, INF);
}
return ret;
}
}
int n, m, s, t, d[MAXN], u[MAXM], v[MAXM], f[MAXM], g[MAXM];
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read(), m = Read(), s = Read(), t = Read();
Flow::Init(n + 1); Flow::S = s; Flow::T = t;
for (int i = 1; i <= m; i ++)
u[i] = Read(), v[i] = Read(), g[i] = Read(), Flow::Addedge(u[i], v[i], g[i] ? 1 : INF), d[u[i]] ++, d[v[i]] --;
for (int i = 1; i <= m; i ++)
if (g[i])
Flow::Addedge(v[i], u[i], INF);
printf("%d\n", Flow::Dinic());
for (int i = 1; i <= m; i ++)
if (g[i])
if (Flow::dis[u[i]] && !Flow::dis[v[i]])
f[i] = 1;
Flow::Init(n + 2); Flow::S = 0, Flow::T = n + 1;
for (int i = 1; i <= m; i ++)
if (g[i])
Flow::Addedge(u[i], v[i], INF);
Flow::Addedge(t, s, INF);
for (int i = 1; i <= n; i ++)
if (d[i] > 0)
Flow::Addedge(i, n + 1, d[i]);
else
Flow::Addedge(0, i, -d[i]);
Flow::Dinic();
for (int i = 1, cnt = 0; i <= m; i ++)
if (!g[i])
puts("0 1");
else
cnt ++, printf("%d %d\n", Flow::e[cnt << 1 | 1].w + 1, Flow::e[cnt << 1 | 1].w + (!f[i]) + 1);
return 0;
}