又垫底了。
和上一场一样,因为 D 题写错了一个小地方,把时间全部耗在上面了。
(还不是水平问题,要是能想到 D 题的最优解法,也就不存在这种问题了。
A. Creating a Character
[str + x > int + epx - x
]
[2x>int+epx-str
]
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
int str, it, ex;
inline void work() {
int p = it - str + ex;
if (p < 0) printf("%d
", ex + 1);
else printf("%d
", std::max(0, ex - p / 2));
}
inline void init() {
read(str), read(it), read(ex);
}
int main() {
#ifdef hzhkk
// freopen("hkk.in", "r", stdin);
#endif
int T;
read(T);
while (T--) {
init();
work();
}
fclose(stdin), fclose(stdout);
return 0;
}
B. Zmei Gorynich
令 (a = max d_i),(b = max d_i - h_i)。
如果能直接用 (a) 杀掉就是 (1)。
否则如果 (b leq 0) 那么无解。
不然就一直用 (b) 直到可以用 (a) 干掉。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 100 + 7;
int n, m, hh1, hh2;
int d[N], h[N];
inline void work() {
if (m > hh1 && hh2 == 0) {
puts("-1");
return;
}
if (m > hh1) printf("%d
", (m - hh1 - 1) / hh2 + 2);
else puts("1");
}
inline void init() {
read(n), read(m);
hh1 = hh2 = 0;
for (int i = 1; i <= n; ++i) {
read(d[i]), read(h[i]);
smax(hh1, d[i]);
smax(hh2, d[i] - h[i]);
}
}
int main() {
#ifdef hzhkk
// freopen("hkk.in", "r", stdin);
#endif
int T;
read(T);
while (T--) {
init();
work();
}
fclose(stdin), fclose(stdout);
return 0;
}
C. The Number Of Good Substrings
显然如果满足条件的 (01) 串,最高位的 (1) 不会在 (18) 位以上。
所以直接暴力。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 2e5 + 7;
int n;
int f[N];
char s[N];
inline void work() {
for (int i = 1; i <= n; ++i)
if (s[i] == '1') f[i] = 0;
else if (s[i - 1] != '0' && s[i] == '0') f[i] = 1;
else f[i] = f[i - 1] + 1;
int ans = 0;
for (int i = 1; i <= n; ++i) {
int now = 0;
for (int j = 0; j <= 18 && j < i; ++j) {
if (s[i - j] == '1') now += 1 << j;
if (now == j + 1) ++ans;
}
if (i > 19 && now > 19 && now <= f[i - 19] + 19) ++ans;
// dbg("i = %d, ans = %d
", i, ans);
}
printf("%d
", ans);
}
inline void init() {
scanf("%s", s + 1);
n = strlen(s + 1);
}
int main() {
#ifdef hzhkk
// freopen("hkk.in", "r", stdin);
#endif
int T;
read(T);
while (T--) {
init();
work();
}
fclose(stdin), fclose(stdout);
return 0;
}
D. Coloring Edges
题意等价于由同色的边构成的子图是一个 (DAG)。
所以如果图中存在环,那么就把由编号小的点指向编号大的点的边颜色记为 (1),反之为 (0)。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 5000 + 7;
int n, m;
int vis[N], ist[N];
pii e[N];
struct Edge { int to, ne; } g[N]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline bool dfs(int x) {
vis[x] = 1, ist[x] = 1;
for fec(i, x, y) {
if (!vis[y]) { if (!dfs(y)) return 0; }
else if (ist[y]) return 0;
}
ist[x] = 0;
return 1;
}
inline void print1() {
puts("1");
for (int i = 1; i <= m; ++i) printf("%d%c", 1, "
"[i == m]);
exit(0);
}
inline void work() {
int flag = 1;
for (int i = 1; i <= n && flag; ++i) if (!vis[i] && !dfs(i)) flag = 0;
if (flag) print1();
puts("2");
for (int i = 1; i <= m; ++i) printf("%d%c", (e[i].fi < e[i].se) + 1, "
"[i == n]);
}
inline void init() {
read(n), read(m);
for (int i = 1; i <= m; ++i) {
int x, y;
read(x), read(y);
addedge(x, y);
e[i].fi = x, e[i].se = y;
}
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
笔者在比赛期间想到一种奇怪的做法, 没有经过严格证明但是可以发现等价于上面的做法。但是由于比赛的时候判断存不存在环没有回溯记录是否在栈中的数组,导致 WA。
思想是按照起点从小到大枚举边,如果把它的颜色计做 (1) 以后,在已经考虑过的边中没有同色环,那么可以为 (1),反之为 (2)。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 5000 + 7;
int n, m, dfc, sccno, tp;
int dfn[N], low[N], scc[N], s[N], vis[N], ans[N], ins[N];
std::vector<pii> v[N];
struct Edge { int to, ne, id, ss; } g[N]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void dfs(int x) {
dfn[x] = low[x] = ++dfc;
s[++tp] = x;
for fec(i, x, y) {
if (!dfn[y]) dfs(y), smin(low[x], low[y]);
else if (!scc[y]) smin(low[x], dfn[y]);
}
if (dfn[x] == low[x]) {
++sccno;
while (1) {
int y = s[tp--];
scc[y] = sccno;
// dbg("scc[%d] = %d
", y, sccno);
if (x == y) break;
}
}
}
inline void tarjan() {
for (int i = 1; i <= n; ++i) if (!dfn[i]) dfs(i);
}
/*
inline void dfs2(int x, int fr = 0) {
dbg("x = %d, fr = %d
", x, fr);
vis[x] = 1;
for (pii i : v[x]) {
int y = i.fi, id = i.se;
ans[id] = fr ^ 1;
if (!vis[y]) dfs2(y, fr ^ 1);
}
}*/
inline bool dfs2(int x, int col) {
vis[x] = 1, ins[x] = 1;
for fec(i, x, y) if (g[i].ss && ans[i] == col) {
if (!vis[y]) { if (!dfs2(y, col)) return 0; }
else if (ins[y]) return 0;
}
ins[x] = 0;
return 1;
}
inline void work() {
tarjan();
int has = 0;
for (int i = 1; i <= sccno; ++i) {
int oe, cnt = 0;
for (int x = 1; x <= n; ++x) if (scc[x] == i) {
for fec(j, x, y) if (scc[y] == i) v[x].pb(pii(g[j].to, g[j].id));
oe = x, ++cnt;
}
if (cnt == 1) continue;
// dbg("*** %d
", cnt);
has = 1;
// dfs2(oe);
}
printf("%d
", has + 1);
// for (int i = 1; i <= m; ++i) printf("%d%c", ans[i] + 1, "
"[i == m]);
for (int x = 1; x <= n; ++x) {
for fec(i, x, y) {
memset(vis, 0, sizeof(vis));
memset(ins, 0, sizeof(ins));
g[i].ss = 1, ans[i] = 0;
if (dfs2(y, 0)) ans[i] = 0;
else ans[i] = 1;
}
}
for (int i = 1; i <= m; ++i) printf("%d%c", ans[i] + 1, "
"[i == m]);
}
inline void init() {
read(n), read(m);
for (int i = 1; i <= m; ++i) {
int x, y;
read(x), read(y);
addedge(x, y);
g[tot].id = i;
}
}
int main() {
#ifdef hzhkk
// freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
E. Sum Queries?
如果选择三个数,肯定不如选择两个数优。
那么对于两个数来说,如果这两个数的集合是满足条件的,那么就意味着存在一位是两个非 (0) 的数字。
直接枚举这一位即可。维护一下第 (i) 位不为 (0) 的数的区间最小值和次小值。
顺便吐槽一下为什么 cf 提交的时候我的代码用 cpp11 提交会 Compilation process timed out
???用 cpp14 就不会有这个问题。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 2e5 + 7;
const int INF = 0x7fffffff;
int n, m;
int a[N], b[N];
inline pii operator + (pii a, pii b) {
if (a > b) std::swap(a, b);
return std::min(a, pii(a.fi, b.fi));
}
struct SGT {
#define lc o << 1
#define rc o << 1 | 1
pii t[N << 2];
inline void build(int o, int L, int R) {
if (L == R) return t[o] = pii(b[L], INF), (void)0;
int M = (L + R) >> 1;
build(lc, L, M), build(rc, M + 1, R);
t[o] = t[lc] + t[rc];
}
inline void qmdf(int o, int L, int R, int x, int k) {
if (L == R) return t[o] = pii(k, INF), (void)0;
int M = (L + R) >> 1;
if (x <= M) qmdf(lc, L, M, x, k);
else qmdf(rc, M + 1, R, x, k);
t[o] = t[lc] + t[rc];
}
inline pii qmin(int o, int L, int R, int l, int r) {
if (l <= L && R <= r) return t[o];
int M = (L + R) >> 1;
if (r <= M) return qmin(lc, L, M, l, r);
if (l > M) return qmin(rc, M + 1, R, l, r);
return qmin(lc, L, M, l, r) + qmin(rc, M + 1, R, l, r);
}
} t[9];
inline void ycl() {
int bn = 1;
for (int i = 0; i < 9; ++i) {
for (int j = 1; j <= n; ++j) b[j] = a[j] / bn % 10 ? a[j] : INF;
bn *= 10;
t[i].build(1, 1, n);
}
}
inline void work() {
ycl();
while (m--) {
int opt, l, r;
read(opt), read(l), read(r);
if (opt == 1) {
int bn = 1;
a[l] = r;
for (int i = 0; i < 9; ++i) t[i].qmdf(1, 1, n, l, r / bn % 10 ? r : INF), bn *= 10;
} else {
int ans = INF;
for (int i = 0; i < 9; ++i) {
pii tp = t[i].qmin(1, 1, n, l, r);
if (tp.se != INF) smin(ans, tp.fi + tp.se);
}
if (ans == INF) puts("-1");
else printf("%d
", ans);
}
}
}
inline void init() {
read(n), read(m);
for (int i = 1; i <= n; ++i) read(a[i]);
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}