标签:学习 暴力 scan ifd answer c++ 必须 first 代码实现
这一场非常的惨啊。
D 题因为一个sb的错误调了一个半小时。然后 E 题根本没有看。
难受。
调回了蓝名。
dollar 可以随便选,euro 必须是 \(5\) 的倍数。可以把 \(e\) 变成 \(5e\) 做。
然后我就很愉快地写了个 \(min(n \bmod d \bmod e, n \bmod e \bmod d)\) 交了上去。
然后 Wrong answer on pretest 7
???
哦想了想好吧,可以枚举 \(d\) 选了多少个。复杂度 \(O(n/d)\)???
看上去复杂度不太靠谱。(其实很靠谱,是我sb了
于是可以小凯的疑惑一波,大于 \(\frac{de}{\gcd(d,e)} - d - e\) 直接对 \(\gcd(d,e)\) 取模。于是这样的复杂度就变成了很靠谱的了。
好吧,我现在已经沦落到连 div2 的 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 * 100 * 5 + 7;
int n, d, e;
int a[N];
inline void work() {
e = 5 * e;
int hkk = std::__gcd(d, e);
if (n / hkk > ((d / hkk) * (e / hkk) - (d / hkk) - (e / hkk))) {
printf("%d\n", n % hkk);
return;
}
for (int i = 0; i <= e && i * d <= n; ++i)
for (int j = 0; j <= d && i * d + j * e <= n; ++j) a[i * d + j * e] = 1;
int ans = 0;
while (!a[n]) ++ans, --n;
printf("%d\n", ans);
}
inline void init() {
read(n), read(d), read(e);
}
int main() {
#ifdef hzhkk
// freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 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;
}
int n, b, g;
inline void work() {
printf("%d\n", std::min(n, b) - std::max(0, n - g) + 1);
}
inline void init() {
read(b), read(g), read(n);
}
int main() {
#ifdef hzhkk
// freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
如果可以通过移动一次解决问题,那么出问题的一定是右括号。所以只需要统计有多少右括号不匹配的。最后应该是不匹配的左括号-不匹配的右括号=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 = 2e5 + 7;
int n;
char s[N];
inline void work() {
int cnt = 0, pri = 1, cc = 0;
for (int i = 1; i <= n; ++i) {
if (s[i] == ')') {
if (!cnt) ++cc;
else --cnt;
} else ++cnt;
}
if (cc > 1 || cnt - cc) {
puts("No");
return;
}
puts("Yes");
}
inline void init() {
read(n);
scanf("%s", s + 1);
}
int main() {
#ifdef hzhkk
// freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
答案只有可能是 \(0, 1, 2\)。
\(0\) 的话就是从起点到不了终点。
主要问题是 \(1\) 和 \(2\) 怎么区分。
如果整个图上堵了一个点以后起点就到不了终点了,那就是 \(1\)。
一开始以为只要有一个割点就可以了。但是这个是有向图。但是是一个 DAG。
于是就写起了支配树。后来发现需要去掉从起点根本到不了的点。
然后就一直 TLE on test 16。一直调到结束。
一直到可以看数据了才发现 dfs 判断从起点可以到哪些点的时候忘了去掉已经走过的点了。
这个错误我也能犯!!!
后面的题目也没有看。
其实这个题还有一种更方便的方法。能堵掉一个点就不连通说明,从起点到终点的所有路径中,存在一个到起点的距离上的点都是同一点。所以直接求一下每个点是不是在起点到终点的路径上(即能到起点能到它,它也能到终点)。
只写了第一种。
#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 = 1e6 + 7;
const int LOG = 3;
int n, m;
char s[2][N], vis[N];
int ans = 2;
int deg[N], f[N][LOG], dep[N], q[N];
struct Edge { int to, ne; } g[N << 2]; 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 adde(int x, int y) { addedge(x, y), addedge(y, x); }
inline int id(int x, int y) { return (x - 1) * m + y; }
inline int LCA(int x, int y) {
// dbg("+++++++++++++++++ x = %d, y = %d\n", x, y);
if (!x || !y) return x ^ y;
if (dep[x] < dep[y]) std::swap(x, y);
for (int i = LOG - 1; i >= 0; --i) if (dep[f[x][i]] >= dep[y]) x = f[x][i];
if (x == y) return x;
// dbg("----------------- x = %d, y = %d\n", x, y);
for (int i = LOG - 1; i >= 0; --i) if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return f[x][0];
}
inline void dfs(int x) {
vis[x] = 1;
for fec(i, x, y) if (!vis[y]) dfs(y);
}
inline void topsort() {
int hd = 0, tl = 0;
for (int i = 1; i <= 1; ++i) if (!deg[i]) q[++tl] = i, f[i][0] = n * m + 1;
while (hd < tl) {
int x = q[++hd];
if (x > 1 && f[x][0] != 1 && f[f[x][0]][0] != 1) f[x][0] = f[f[x][0]][0];
dep[x] = dep[f[x][0]] + 1;
// dbg("x = %d, f[x][0] = %d\n", x, f[x][0]);
// dbg("x = %d\n", dep[x]);
for (int i = 1; i < LOG; ++i) f[x][i] = f[f[x][i - 1]][i - 1];
for fec(i, x, y) {
if (!--deg[y]) q[++tl] = y;
f[y][0] = LCA(f[y][0], x);
// dbg("********* %d %d %d\n", x, y, deg[y]);
}
}
}
inline void work() {
dfs(1);
for (int i = 1; i <= n * m; ++i)
if (vis[i])
for fec(j, i, y) ++deg[y];
topsort();
if (!vis[n * m]) puts("0");
else if (f[n * m][0] != 1) puts("1");//, dbg("*** %d\n", f[n * m][0]);
else puts("2");
}
inline void init() {
read(n), read(m);
int now = 0, pre = 1;
for (int i = 1; i <= n; ++i) {
std::swap(now, pre);
scanf("%s", s[now] + 1);
for (int j = 1; j <= m; ++j) {
if (j > 1 && s[now][j - 1] == '.' && s[now][j] == '.') addedge(id(i, j - 1), id(i, j));
if (i > 1 && s[pre][j] == '.' && s[now][j] == '.') addedge(id(i - 1, j), id(i, j));
}
}
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
一个直观的想法是先拿出一部分点构造一条链,然后在上面追加点。
如果点 \(2i-1\) 位于链的 \(x\) 位,那么我们就要在链的第 \(x+d_i-1\)个点后面加上点 \(2i\) 就可以了。
但是要保证第 \(x+d_i-1\) 个点存在啊。
不妨假设第 \(x-1\) 位上是 \(2j-1\),这个点已经成功对接了。因为新加一个点最好情况下会给链加上一个点,那么有 \(x-1+d_j \leq len\),其中 \(len\) 为加上 \(2j-1\) 以后的链最长的长度。
发现只要我们能够保证 \(x+d_i-1\leq x-1+d_j\) 就可以了。也就是 \(d_i \leq d_j\)。这完全是可以实现的。
所以把 \(d\) 数组从大到小排序,然后按上面说的来处理就可以了。
#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 = 1e5 + 7;
int n;
int b[N], s[N], id[N << 1], pre[N << 1];
struct wph {
int d, id;
} a[N];
inline void add(int x, int fa, int tag = 1) {
if (tag) s[x] = s[fa] + 1, b[s[x]] = x;
printf("%d %d\n", x, fa);
}
inline void work() {
std::sort(a + 1, a + n + 1, [](const wph &a, const wph &b) {
return a.d > b.d;
});
for (int i = 1; i < n; ++i) printf("%d %d\n", a[i].id * 2 - 1, a[i + 1].id * 2 - 1);
for (int i = 1; i <= n; ++i) id[i] = a[i].id * 2 - 1;
int nn = n;
for (int i = 1; i <= n; ++i)
if (i + a[i].d - 1 < nn) printf("%d %d\n", id[i] + 1, id[i + a[i].d - 1]);
else id[++nn] = id[i] + 1, printf("%d %d\n", id[nn], id[nn - 1]);
}
inline void init() {
read(n);
for (int i = 1; i <= n; ++i) read(a[i].d), a[i].id = i;
}
int main() {
#ifdef hzhkk
// freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
挺好的题。
一直显然的贪心是把 \(a\) 和 \(b\) 分别排序,然后对应位算距离就可以了。
但是由于这是一个环,所以不知道到底哪一位对应哪一位。
所以可以枚举 \(a_1\) 和 \(b_i\) 对应。\(O(n^2)\)。
写了一个这样的暴力,发现是对的。
然后就不会了,题解里面是这样说的:
对于两个坐标 \(x, y\),他们的距离只有可能是这四种情况。
就只看了这么一点,所以貌似最后写出了都东西和大部分人不太一样。
然后发现对于每一个 \(a_i\),在枚举对应的 \(b_j\) 时,上面四种情况都是连续的 \(b_j\)。于是枚举坐标差,直接在有情况改变的坐标差处处理一下就可以了。
代码实现非常复杂,细节很多。(仅限于上面的做法
(貌似大部分人写的和这个不一样,没有去学习
#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, m;
int aa[N], sta[N], a[N], b[N], sta2[N];
pii sa[N], sb[N];
std::vector<pii> v[N], v2[N];
inline int dis(int x, int y) {
if (x > y) std::swap(x, y);
return std::min(y - x, x + n - y);
}
/*
inline void work() {
std::sort(a + 1, a + m + 1);
std::sort(b + 1, b + m + 1);
ll ans = 0x7fffffffffffffff, pos;
for (int i = 1; i <= m; ++i) {
ll cnt = 0;
for (int j = 1; j <= m; ++j) cnt += dis(a[j].fi, b[(i + j - 2) % m + 1].fi);
smin(ans, cnt) && (pos = i);
}
dbg("pos = %d\n", pos);
for (int i = 1; i <= m; ++i) aa[a[i].se] = b[(i + pos - 2) % m + 1].se;
printf("%I64d\n", ans);
for (int i = 1; i <= m; ++i) printf("%d%c", aa[i], " \n"[i == n]);
}*/ // That's force;
inline int ff(int x) { return std::upper_bound(b + 1, b + m + 1, x) - b - 1; }
inline int f2(int x) { return std::lower_bound(a + 1, a + m + 1, x) - a; }
inline void work() {
std::sort(sa + 1, sa + m + 1);
std::sort(sb + 1, sb + m + 1);
for (int i = 1; i <= m; ++i) a[i] = sa[i].fi, b[i] = sb[i].fi;
int n2 = n / 2;
for (int i = 1; i <= m; ++i) {
int p1 = a[i] - n2 - 1, p2 = a[i] - 1, p3 = a[i] + n / 2, p4 = n;
// dbg("i = %d, p1 = %d, p2 = %d, p3 = %d, p4 = %d\n", i, p1, p2, p3, p4);
p1 = ff(p1) % m, p2 = ff(p2) % m, p3 = ff(p3) % m, p4 = ff(p4) % m;
// dbg("i = %d, p1 = %d, p2 = %d, p3 = %d, p4 = %d\n", i, p1, p2, p3, p4);
if (p1 != p2) v[(p1 - i + 1 + m) % m].pb(pii(i, 1));
if (p2 != p3) v[(p2 - i + 1 + m) % m].pb(pii(i, 2));
if (p3 != p4) v[(p3 - i + 1 + m) % m].pb(pii(i, 3));
if (p4 != p1) v[(p4 - i + 1 + m) % m].pb(pii(i, 0));
}
for (int i = 1; i <= m; ++i) {
int p1 = b[i] - n2, p2 = b[i] + 1, p3 = b[i] + n / 2 + 1, p4 = 1;
// dbg("i = %d, p1 = %d, p2 = %d, p3 = %d, p4 = %d\n", i, p1, p2, p3, p4);
p1 = f2(p1) % m, p2 = f2(p2) % m, p3 = f2(p3) % m, p4 = f2(p4) % m;
// dbg("i = %d, p1 = %d, p2 = %d, p3 = %d, p4 = %d\n", i, p1, p2, p3, p4);
if (p1 != p4) v2[(-p1 + i + 1 + m) % m].pb(pii(i, 3));
if (p2 != p1) v2[(-p2 + i + 1 + m) % m].pb(pii(i, 2));
if (p3 != p2) v2[(-p3 + i + 1 + m) % m].pb(pii(i, 1));//, i == 3 && dbg("********** %d\n", (-p3 + i + 1 + m) % m);
if (p4 != p3) v2[(-p4 + i + 1 + m) % m].pb(pii(i, 0));
}
ll sum_a[4] = {0}, sum_b[4] = {0}, pos, cnt[4] = {0}, cnt2[4] = {0};
ll ans = 0x7fffffffffffffff;
memset(sta, -1, sizeof(sta));
// for (int i = 0; i < 4; ++i) for (pii j : v[i]) sum_a[j.se] += a[j.fi], sum_b[j.se] += b[j.fi], ++cnt[j.se], sta[j.fi] = j.se;
for (int i = 1; i <= m; ++i) {
int x = i, y;
if (b[i] < a[i] - n2) y = 0;
else if (b[i] < a[i]) y = 1;
else if (b[i] <= a[i] + n2) y = 2;
else y = 3;
// dbg("******************** %d %d\n", x, y);
sum_a[y] += a[x], sum_b[y] += b[x], cnt[y] += 1, cnt2[y] += 1;
sta[x] = y, sta2[x] = y;
}
for (int i = 1; i <= m; ++i) {
// dbg("i = %d, \n", i);
// for (int j = 0; j < 4; ++j) dbg("sum_a[%d] = %lld, sum_b = %lld, cnt = %lld, cnt2 = %lld, %lld\n", j, sum_a[j], sum_b[j], cnt[j], cnt2[j], sum_b[0] + n * cnt[0] - sum_a[0] + sum_a[1] - sum_b[1] + sum_b[2] - sum_a[2] + sum_a[3] + n * cnt[3] - sum_b[3]);
if (i) smin(ans, sum_b[0] + n * cnt[0] - sum_a[0] + sum_a[1] - sum_b[1] + sum_b[2] - sum_a[2] + sum_a[3] + n * cnt[3] - sum_b[3]) && (pos = i);
if (cnt[0] != cnt2[0] || cnt[1] != cnt2[1] || cnt[2] != cnt2[2] || cnt[3] != cnt2[3]) {
//// printf("(%I64d, %I64d, %I64d, %I64d, %I64d, %I64d, %I64d, %I64d)\n", cnt[0], cnt2[0], cnt[1], cnt2[1], cnt[2], cnt2[2], cnt[3], cnt2[3]);
// int dd = sum_b[3];
// int x = std::lower_bound(b + 1, b + n + 1, dd) - b;
// printf("**** x = %d, i = %d, %d %d\n", x, i, dd, a[(x - i + 1 + m - 1) % m + 1]);
// printf("***************** %d %d\n", a[m], b[m]);{
// int i = m;
// int p1 = a[i] - n2 - 1, p2 = a[i] - 1, p3 = a[i] + n / 2, p4 = n;
// // dbg("i = %d, p1 = %d, p2 = %d, p3 = %d, p4 = %d\n", i, p1, p2, p3, p4);
// p1 = ff(p1) % m, p2 = ff(p2) % m, p3 = ff(p3) % m, p4 = ff(p4) % m;
// dbg("i = %d, p1 = %d, p2 = %d, p3 = %d, p4 = %d\n", i, p1, p2, p3, p4);
// if (p1 != p2) v[(p1 - i + 1 + m) % m].pb(pii(i, 1));
// if (p2 != p3) v[(p2 - i + 1 + m) % m].pb(pii(i, 2));
// if (p3 != p4) v[(p3 - i + 1 + m) % m].pb(pii(i, 3));
// if (p4 != p1) v[(p4 - i + 1 + m) % m].pb(pii(i, 0));
// }
return;
}
for (pii j : v[i]) {
int x = j.fi, &y = sta[x];
// dbg("v1 : i = %d, x = %d, sta[x] = %d, y = %d\n", i, x, sta[x], j.se);
if (~y) sum_a[y] -= a[x], cnt[y] -= 1;
y = j.se;
sum_a[y] += a[x], cnt[y] += 1;
}
for (pii j : v2[i]) {
int x = j.fi, &y = sta2[x];
// dbg("v2 : i = %d, x = %d, sta[x] = %d, y = %d\n", i, x, sta2[x], j.se);
if (~y) sum_b[y] -= b[x], cnt2[y] -= 1;
y = j.se;
sum_b[y] += b[x], cnt2[y] += 1;
}
// dbg("ans = %lld\n", ans);
}
printf("%I64d\n", ans);
for (int i = 1; i <= m; ++i) aa[sa[i].se] = sb[(i + pos - 2) % m + 1].se;
for (int i = 1; i <= m; ++i) printf("%d%c", aa[i], " \n"[i == n]);
}
inline void init() {
read(n), read(m);
for (int i = 1; i <= m; ++i) read(sa[i].fi), sa[i].se = i;
for (int i = 1; i <= m; ++i) read(sb[i].fi), sb[i].se = i;
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises)
标签:学习 暴力 scan ifd answer c++ 必须 first 代码实现
原文地址:https://www.cnblogs.com/hankeke/p/CF1214.html