Educational Codeforces Round 16
https://codeforces.com/contest/710
4/6:ABCE
A. King Moves
#include <bits/stdc++.h>
using namespace std;
int cnt, ans;
int main () {
char c;
int n;
cin >> c >> n;
if (c == 'h') cnt ++;
if (c == 'a') cnt ++;
if (n == 1) cnt ++;
if (n == 8) cnt ++;
if (!cnt) ans = 8;
else if (cnt == 1) ans = 5;
else if (cnt == 2) ans = 3;
cout << ans;
}
B. Optimal Point on a Line
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5;
int a[N], n;
int main () {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
sort (a + 1, a + n + 1);
cout << a[(n+1)/2];
}
//中位数
C. Magic Odd Square
菱形构造
#include <bits/stdc++.h>
using namespace std;
const int N = 2505;
int a[N][N], n;
int main () {
cin >> n;
int m = n / 2 + 1;
for (int i = 1; i <= m; i++) {
for (int j = m - i + 1; j <= m; j++) {
a[i][j] = a[i][n-j+1] = a[n-i+1][j] = a[n-i+1][n-j+1] = 1;
}
}
int odd = 1, even = 2;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
//cout << a[i][j] << ' ';
if (a[i][j]) cout << odd << ' ', odd += 2;
else cout << even << ' ' , even += 2;
}
cout << endl;
}
}
//没看到是奇数呜呜呜
//菱形
D. Two Arithmetic Progressions
E. Generate a String
线性dp。
注意两个细节:见代码注释。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e7 + 5, inf = 1e18;
int n, a, b;
int f[N][3]; //选择方式
signed main () {
cin >> n >> a >> b;
memset (f, 0x3f, sizeof f);
f[1][0] = a;
for (int i = 2; i <= n; i++) {
f[i][0] = min ({f[i-1][0], f[i-1][1], f[i-1][2]}) + a;
//f[i][1] = min ({f[i+1][0], f[i+1][1], f[i+1][2]}) + a; //不能用未更新的状态i+1来更新i
if (i & 1) {
f[i][2] = min ({f[i/2+1][0], f[i/2+1][1], f[i/2+1][2]}) + b + a;
//f[i][2] = min(f[i][2], min ({f[i/2][0], f[i/2][1], f[i/2][2]})) + b + a; //删除操作一定不会连续进行两次所以这个不优
}
else f[i][2] = min ({f[i/2][0], f[i/2][1], f[i/2][2]}) + b;
}
//cout << f[n][0] << ' ' << f[n][1] << ' ' << f[n][2] << endl;
cout << min({f[n][0], f[n][1], f[n][2]});
}
题解版本:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e7 + 5;
int n, a, b;
int f[N]; //选择方式
signed main () {
cin >> n >> a >> b;
memset (f, 0x3f, sizeof f);
f[1] = a;
for (int i = 2; i <= n; i++) {
if (i & 1) f[i] = min (f[(i+1)/2] + a + b, f[i-1] + a);
else f[i] = min (f[i/2] + b, f[i-1] + a);
}
cout << f[n];
}
//删除操作一定不会连续进行两次
F. String Set Queries
数据结构,字符串。
ACAM做法
// LUOGU_RID: 99575335
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e5 + 5;
char s[N];
struct ACAM {
int trans[N][26], tr[N][26], fail[N];
int idx, tot, rt[N], sz[N];
int que[N], cnt[N], sum[N];
void insert(char s[], int& root) {
if (!root) root = ++idx;
int p = root;
for (int i = 0; s[i]; i++) {
int c = s[i] - 'a';
if (!tr[p][c]) tr[p][c] = ++idx;
p = tr[p][c];
}
cnt[p]++;
}
void build(int root) {
int tt = -1, hh = 0;
fail[root] = root;
for (int i = 0; i < 26; i++) {
if (tr[root][i]) {
trans[root][i] = tr[root][i];
que[++tt] = tr[root][i];
fail[tr[root][i]] = root;
}
else trans[root][i] = root;
}
// 一般的ac自动机root默认为0 所以不需要特意赋fail指针
// 但是这里需要
while (hh <= tt) {
int t = que[hh++];
for (int i = 0; i < 26; i++) {
int p = tr[t][i], &q = trans[t][i];
if (!p) q = trans[fail[t]][i];
else {
q = p;
fail[q] = trans[fail[t]][i];
que[++tt] = q;
}
}
sum[t] = cnt[t] + sum[fail[t]];
}
}
int merge(int& u, int& v) {
if (!u || !v) return u | v;
cnt[u] += cnt[v];
for (int i = 0; i < 26; i++) tr[u][i] = merge(tr[u][i], tr[v][i]);
return u;
}
void insert(char s[]) {
sz[++tot] = 1;
rt[tot] = ++idx;
insert(s, rt[tot]);
while (sz[tot] == sz[tot - 1]) {
sz[--tot] <<= 1;
rt[tot] = merge(rt[tot], rt[tot + 1]);
}
build(rt[tot]);
}
ll query(char s[]) {
int p = 0;
ll res = 0;
for (int i = 1; i <= tot; i++) {
int p = rt[i];
for (int j = 0; s[j]; j++) {
int c = s[j] - 'a';
p = trans[p][c];
res += sum[p];
}
}
return res;
}
} add, del;
int main () {
int n;
cin >> n;
while (n --) {
int op;
cin >> op >> s;
if (op == 1) add.insert (s);
else if (op == 2) del.insert (s);
else cout << add.query(s) - del.query(s) << endl;
}
}