Presentation
第一次打CC
上一次作死最后几个小时报了名打了三题
裸题比较的多吧。。前面的几题都有一些小细节要注意。
还是大佬厉害啊。最开始直接达到了
rank1
。
最后Challenge不想做了啊 (其实就是做不来)
只有
rank19
啦。。
不过最后两道题还是学到了一些东西的。
Solution
1.PERFCONT
#include <bits/stdc++.h>
using namespace std;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}
int test, n, p, x;
int e, h;
int main(void) {
read(test);
while (test--) {
e = h = 0;
read(n); read(p);
for (int i = 1; i <= n; i++) {
read(x);
if (x >= p / 2) ++e;
if (x <= p / 10) ++h;
}
if (e == 1 && h == 2) puts("yes");
else puts("no");
}
return 0;
}
2.MEX
#include <bits/stdc++.h>
using namespace std;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}
int test, n, p, x;
int e, h;
int main(void) {
read(test);
while (test--) {
e = h = 0;
read(n); read(p);
for (int i = 1; i <= n; i++) {
read(x);
if (x >= p / 2) ++e;
if (x <= p / 10) ++h;
}
if (e == 1 && h == 2) puts("yes");
else puts("no");
}
return 0;
}
3.CHEFCOUN
xjb构造就好了。。
using namespace std;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}
const int N = 202020;
typedef unsigned ui;
int n, test;
ui a[N], mx, sum, S;
ui pre[N];
int main(void) {
read(test);
mx = (1ll << 32) - 1;
while (test--) {
read(n); sum = S = 0;
S = mx;
int i;
for (i = 1; i <= n; i++) {
if (S < 100001 + (n - i)) break;
a[i] = 100000; S -= 100000;
}
a[i] = 2;
for (++i; i <= n; i++) a[i] = 1;
for (i = 1; i <= n; i++) printf("%d\n", a[i]);
putchar('\n');
}
return 0;
}
4.CHEFCOUN
贪心题。考虑把
a
插到
题意最开始好像有问题。。搞了很久的样子。
#include <bits/stdc++.h>
using namespace std;
const int N = 201010;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
inline void read(int &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}
int test, n, a, b, x, y;
char ch[N];
struct cpp {
int len, Ans;
char ans[N];
inline char &operator [](int x) {
return ans[x];
}
inline bool operator <(const cpp &a) {
return Ans < a.Ans;
}
};
cpp Ans, tmp;
inline void Solve(int a, int b, char A, char B, int x, int y) {
int i, c, ls, d = a / x, e = a % x; tmp.len = 0; tmp.Ans = 0;
if (b < d) {
for (c = 0; c < b; ++c) {
for (int j = 0; j < x; j++) tmp[tmp.len++] = A;
tmp[tmp.len++] = B;
}
ls = 0;
for (i = b * (x + 1); i < n; i++) {
if (ls == x) {
tmp[tmp.len++] = '*';
tmp.Ans++; ls = 0;
}
tmp[tmp.len++] = A; ++ls;
}
if (tmp.Ans < Ans.Ans) Ans = tmp;
} else {
b -= d;
for (c = 0; c < d; ++c) {
for (int j = 0; j < x; j++) {
for (i = 0; i < y - (j == 0 && c != 0) && b; i++) --b, tmp[tmp.len++] = B;
tmp[tmp.len++] = A;
}
tmp[tmp.len++] = B;
}
for (c = 0; c < e; ++c) {
for (i = 0; i < y - (c == 0) && b; i++) --b, tmp[tmp.len++] = B;
tmp[tmp.len++] = A;
}
ls = 0;
for (int i = tmp.len - 1; i; i--)
if (tmp[i] == B) ++ls;
else break;
for (int i = 0; i < b; i++) {
if (ls == y) {
tmp[tmp.len++] = '*';
tmp.Ans++; ls = 0;
}
tmp[tmp.len++] = B; ++ls;
}
if (tmp.Ans < Ans.Ans) Ans = tmp;
}
}
int main(void) {
scanf("%d\n", &test);
while (test--) {
a = b = 0; scanf("%s", ch);
n = strlen(ch);
for (int i = 0; i < n; i++)
if (ch[i] == 'a') ++a;
else ++b;
scanf("%d %d\n", &x, &y);
Ans.Ans = N;
Solve(a, b, 'a', 'b', x, y);
Solve(b, a, 'b', 'a', y, x);
int lsa = 0, lsb = 0;
for (int i = 0; i < Ans.len; i++)
putchar(Ans[i]);
putchar('\n');
}
return 0;
}
5.CHEFCOUN
因为总共只有两条最短路径,xjb判一判就好了。
#include <bits/stdc++.h>
using namespace std;
const int N = 301010;
typedef long long ll;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}
template<typename T>
inline T Min(T a, T b) {
return a < b ? a : b;
}
struct Cycle {
vector<ll> val;
int sz;
ll sum;
inline void Init(void) {
val.clear(); read(sz);
val.resize(sz + 3); sum = 0;
val[0] = 0;
for (int i = 1; i <= sz; i++) {
read(val[i]); sum += val[i];
}
for (int i = 1; i <= sz; i++)
val[i] += val[i - 1];
}
inline void Print(void) {
for (int i = 1; i <= sz; i++) printf("%d ", val[i]);
putchar('\n');
}
inline ll Dist(int x, int y) {
if (x > y) swap(x, y);
return Min(val[y - 1] - val[x - 1], sum - val[y - 1] + val[x - 1]);
}
};
Cycle a[N];
int test, n, m, q, x, y, z, v1, c1, v2, c2;
int in[N], out[N];
ll val[N], dis[N];
ll sum, res, ans, S;
int p;
int main(void) {
read(test);
while (test--) {
read(n); read(q); S = sum = 0; val[0] = 0;
for (int i = 1; i <= n; i++) a[i].Init();
for (int i = 1; i <= n; i++) {
read(out[i]); read(in[i % n + 1]);
read(z); val[i] = z; sum += z;
}
for (int i = 1; i <= n; i++) dis[i] = a[i].Dist(in[i], out[i]);
for (int i = 1; i <= n; i++) {
val[i] += val[i - 1];
S += dis[i];
dis[i] += dis[i - 1];
}
while (q--) {
read(v1); read(c1); read(v2); read(c2);
if (c1 > c2) {
swap(c1, c2); swap(v1, v2);
}
p = a[c1].Dist(v1, out[c1]);
p = a[c2].Dist(in[c2], v2);
res = a[c1].Dist(v1, out[c1]) + val[c2 - 1] - val[c1 - 1] + a[c2].Dist(in[c2], v2) + dis[c2 - 1] - dis[c1];
ans = res;
res = a[c1].Dist(v1, in[c1]) + sum - val[c2 - 1] + val[c1 - 1] + a[c2].Dist(out[c2], v2) + S - dis[c2] + dis[c1 - 1];
ans = Min(res, ans);
printf("%lld\n", ans);
}
}
return 0;
}
6.MARRAYS
直接DP,对一个元素维护一个前缀和后缀,这样就没有绝对值的影响。就可以
O(1)
转移了。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 1010101;
const long long INF = 1ll << 50;
typedef long long ll;
typedef pair<int, ll> P;
int n;
vector<int> a[N];
vector<ll> pre[N],suf[N];
vector<P> dp[N];
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
inline void read(int &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}
inline void ReStore(int x,int y) {
a[x].resize(y); pre[x].resize(y); suf[x].resize(y); dp[x].resize(y);
}
inline bool cmp(P a,int b) {
return a.first < b;
}
int main() {
int t; read(t);
while (t--) {
read(n);
for (int i = 1; i <= n; i++) {
int m, x; read(m); ReStore(i, m);
for (int j = 0; j<m; j++) {
read(a[i][j]);
dp[i][j] = P(a[i][j], 0);
}
}
for (int i = 2; i <= n; i++) {
sort(dp[i - 1].begin(), dp[i - 1].end());
int m = a[i - 1].size();
pre[i - 1][0] = dp[i - 1][0].second - (ll)dp[i - 1][0].first * (i - 1);
suf[i - 1][m - 1] = dp[i - 1][m - 1].second + (ll)dp[i - 1][m - 1].first * (i - 1);
for (int j = 1; j < m; j++)
pre[i - 1][j] = max(pre[i - 1][j - 1], dp[i - 1][j].second - (ll)dp[i - 1][j].first * (i - 1));
for (int j = m - 2; ~j; j--)
suf[i - 1][j] = max(suf[i - 1][j + 1], dp[i - 1][j].second + (ll)dp[i - 1][j].first * (i - 1));
m = a[i].size(); int mm = a[i - 1].size();
for (int j = 0; j < m; j++) {
int nxt = (j + m - 1) % m, p = lower_bound(dp[i - 1].begin(), dp[i - 1].end(), a[i][j], cmp) - dp[i - 1].begin();
if (a[i][j] <= dp[i - 1][0].first)
dp[i][nxt].second = suf[i - 1][0] - (ll)a[i][j] * (i - 1);
else if (a[i][j] >= dp[i - 1][mm - 1].first)
dp[i][nxt].second = pre[i - 1][mm - 1] + (ll)a[i][j] * (i - 1);
else
dp[i][nxt].second = max(pre[i - 1][p] + (ll)a[i][j] * (i - 1), suf[i - 1][p] - (ll)a[i][j] * (i - 1));
}
}
ll ans = 0;
for (int i = 0; i < a[n].size(); i++)
ans = max(ans, dp[n][i].second);
cout << ans << endl;
for (int i = 1; i <= n; i++) {
a[i].clear(); pre[i].clear();
suf[i].clear(); dp[i].clear();
}
}
return 0;
}
7.POINTCN
Challenge
是真的做不来
8.SHTARR
又想起了CC的COT5
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 1010101;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}
inline void reado(char &opt) {
for (opt = get(); opt != '?' && opt != '+'; opt = get());
}
int mx[N << 2];
int ans[N << 2];
int l[N << 2], r[N << 2];
int a[N];
int n, q, x, y, z, test, L, R, res, Ans, MX, tmp, pos, t, p;
char opt;
template<typename T>
inline T Max(T a, T b) {
return a > b ? a : b;
}
inline int Calc(int o, double v) {
if (l[o] == r[o]) return mx[o] > v;
if (v > mx[o << 1]) return Calc(o << 1 | 1, v);
return Calc(o << 1, v) + ans[o] - ans[o << 1];
}
void Build(int o, int _l, int _r) {
l[o] = _l; r[o] = _r;
ans[o] = (a[_l] > 0); mx[o] = a[_l];
if (_l == _r) return;
int mid = (_l + _r) >> 1;
Build(o << 1, _l, mid);
Build(o << 1 | 1, mid + 1, _r);
mx[o] = Max(mx[o << 1], mx[o << 1 | 1]);
ans[o] = ans[o << 1] + Calc(o << 1 | 1, mx[o << 1]);
}
void Modify(int o, int pos, int x) {
if (l[o] == r[o]) {
mx[o] = x; ans[o] = 1;
return;
}
int mid = (l[o] + r[o]) >> 1;
if (pos <= mid) Modify(o << 1, pos, x);
else Modify(o << 1 | 1, pos, x);
mx[o] = Max(mx[o << 1], mx[o << 1 | 1]);
ans[o] = ans[o << 1] + Calc(o << 1 | 1, mx[o << 1]);
}
inline void QAns(int o, int L, int R) {
if (l[o] >= L && r[o] <= R) {
tmp += Calc(o, MX);
MX = Max(MX, mx[o]);
return;
}
int mid = (l[o] + r[o]) >> 1;
if (R <= mid) return QAns(o << 1, L, R);
if (L > mid) return QAns(o << 1 | 1, L, R);
QAns(o << 1, L, R); QAns(o << 1 | 1, L, R);
}
inline int QAns(int x) {
tmp = 0; MX = -1; QAns(1, x, n + 1);
return tmp;
}
int main(void) {
read(test);
while (test--) {
read(n); read(q);
for (int i = 1; i <= n; i++) read(a[i + 1]);
Build(1, 1, n + 1);
for (int i = 1; i <= q; i++) {
reado(opt);
if (opt == '+') {
read(x); read(y);
Modify(1, x + 1, a[x + 1] += y);
} else {
read(x); read(L); read(R);
Modify(1, x, L - 1); res = QAns(x) - 1;
Modify(1, x, R); t = QAns(x) - 1;
Modify(1, x, R - 1); p = QAns(x) - 1;
printf("%d\n", res - t + (p == t && p));
Modify(1, x, a[x]);
}
}
}
return 0;
}
9.LKYEDGE
枚举左端点
l
然后考虑建一颗以边存在时间为权值的最小生成树,那么会是lucky edge的边就是非树边,以及被他覆盖的边,直接暴力爬树就好了。
每次修改要缩点,因为后统计的一定会包含之前统计的里面。
#include <bits/stdc++.h>
using namespace std;
const int N = 10101;
const int M = 5050;
typedef pair<int, int> P;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
inline void read(int &x) {
static char c; x = 0;
for (c = get(); c <'0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}
struct edge {
int to, next, id;
edge (int t = 0, int n = 0, int i = 0):to(t), next(n), id(i) {}
};
edge G[M << 1];
int fa[N], rk[N], fat[N];
int n, m, p1, p2, x, y, z, Gcnt, test, clc, ccl, lca, Wcnt, r;
int head[N], vis[N], vst[N], pre[N];
int ans[N], id[N], dep[N], rak[N], num[N];
P E[M], E1[M];
inline int Head(int x) {
if (vis[x] == clc) return head[x];
vis[x] = clc; return head[x] = 0;
}
inline void AddEdge(int from, int to, int id = 0) {
G[++Gcnt] = edge(to, Head(from), id); head[from] = Gcnt;
G[++Gcnt] = edge(from, Head(to), id); head[to] = Gcnt;
}
inline int Fa(int x) {
return fa[x] == x ? x : fa[x] = Fa(fa[x]);
}
inline int Merge(int x, int y) {
static int f1, f2;
f1 = Fa(x); f2 = Fa(y);
if (f1 == f2) return false;
if (rk[f1] < rk[f2]) swap(f1, f2);
if (rk[f1] == rk[f2]) rk[f1]++;
fa[f2] = f1; return true;
}
inline void dfs(int u, int f) {
dep[u] = dep[f] + 1; vst[u] = ccl; fat[u] = f;
for (int i = Head(u); i; i = G[i].next) {
if (G[i].to != fat[u]) dfs(G[i].to, u);
pre[G[i].to] = G[i].id;
}
}
inline int LCA(int x, int y) {
while (x != y) {
if (dep[x] < dep[y]) swap(x, y);
if (x != fa[x]) x = fa[x];
else x = fat[x];
}
return x;
}
int main(void) {
read(test);
while (test--) {
read(m); n = 0;
for (int i = 0; i < m; i++) {
read(x); read(y);
E[i] = P(x, y); ans[i] = 0;
id[n++] = x; id[n++] = y;
dep[x] = dep[y] = 0;
}
sort(id, id + n);
n = unique(id, id + n) - id;
for (int i = 0; i < n; i++) rak[id[i]] = i + 1;
for (int i = 0; i < m; i++) E[i] = P(rak[E[i].first], rak[E[i].second]);
for (int l = 0; l < m; l++) {
p1 = Gcnt = 0; ++clc;
for (int i = 1; i <= n; i++) fa[i] = i;
for (int i = l; i < m; i++) {
if (Merge(E[i].first, E[i].second))
AddEdge(E[i].first, E[i].second, i);
else {
num[p1] = i; E1[p1++] = E[i];
}
}
++ccl;
for (int i = 1; i <= n; i++) {
fa[i] = i;
}
for (int i = 0; i < p1; i++) {
x = E1[i].first; y = E1[i].second;
z = m - num[i]; ans[num[i]] += z;
x = Fa(x); y = Fa(y);
if (vst[x] != ccl) dfs(x, 0);
lca = LCA(x, y);
if (y == lca || x == lca) {
if (x == lca) swap(x, y);
for (; dep[Fa(x)] > dep[lca]; x = r) {
if (Fa(x) == x) {
ans[pre[x]] += z; r = fat[x];
} else r = Fa(x);
fa[x] = fa[lca];
}
} else {
for (; dep[Fa(x)] > dep[lca]; x = r) {
if (Fa(x) == x) {
ans[pre[x]] += z; r = fat[x];
} else r = Fa(x);
fa[x] = fa[lca];
}
x = y;
for (; dep[Fa(x)] > dep[lca]; x = r) {
if (Fa(x) == x) {
ans[pre[x]] += z; r = fat[x];
} else r = Fa(x);
fa[x] = fa[lca];
}
}
}
}
for (int i = 0; i < m; i++)
printf("%d ", ans[i]);
putchar('\n');
}
return 0;
}

本文分享了一次CC竞赛的经历,详细记录了解决从PERFCONT到XORTREEH共10道题目的过程,并提供了每道题目的代码实现,涵盖了算法技巧如贪心策略、动态规划等。
2917

被折叠的 条评论
为什么被折叠?



