Educational Codeforces Round 97 (Rated for Div. 2)
阿新 • • 發佈:2020-10-29
A
在 l ~ r 之間肯定不行
當 a > r, 則 l >= a/2 即 r < a <= 2l, 即 r < 2l
當 a < l, 則 r / (a/2) - (l-1) / (a/2) ≡ 0, 即 r - l + 1 < a / 2 即 2r - 2l + 2 < a < l
即 2r - 2l + 2 + 1 < l 與 l < r 相悖不存在 a < l
int main() { IOS; for (cin >> _; _; --_) { ll a, b; cin >> a >> b; if (a * 2 > b) cout << "YES\n"; else cout << "NO\n"; } return 0; }
B
每次操作 消除一個 00 或 11
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; cin >> s + 1;
int ans = 0, cur = 0;
rep (i, 2, n)
if (s[i] == s[i - 1]) ++ans;
cout << (ans + 1) / 2 << '\n';
}
return 0;
}
C
01揹包
dp, 揹包容量為 2n (即所有物品從 n 開始放 放到 2n - 1), 你不會把 n 個物品瘋狂往後放吧, 肯定不是最小值
int main() { IOS; for (cin >> _; _; --_) { cin >> n; rep(i, 1, n) cin >> a[i]; sort(a + 1, a + 1 + n); rep(j, 1, n) f[j] = 1e15; rep(i, 1, n << 1) per(j, min(n, i), 1) umin(f[j], f[j - 1] + abs(i - a[j])); cout << f[n] << '\n'; } return 0; }
D
我是sb, 我是sb, 我是sb
腦子沒轉過來彎
連續遞增的一段可以作為 兄弟節點
其之後的每個連續段(即兄弟節點), 可以依次放在 前一段遞增序列 的下面, 作為其子節點
(就是這裡,我卡住了, 為啥能依次放啊? 我一直卡在只能放在 前一段遞增序列 的最後一個節點上, 怎麼著都轉不過來彎)
我是sb, 我是sb, 我是sb
int main() {
IOS; a[1] = 1;
for (cin >> _; _; --_) {
cin >> n >> m;
rep (i, 2, n) {
cin >> a[i];
if (a[i] < a[i - 1]) ++m;
h[i] = h[m] + 1;
}
cout << h[n] << '\n';
}
return 0;
}
G
為啥不敢去看G啊, 原來難度不一定遞增啊
這tm就是一道 AC自動機裸體, 改一點點就行, 可以看看我置頂的 字串 板子
這就是套板子完事, 思維也沒考, 就考個資料結構, 這也能放在G....
struct AC {
static const int N = 3e5 + 5, M = 26, C = 'a'; //字串總長度, 字元範圍
int trie[N][M], cnt[N], fail[N], vis[N], tot;
vector<multiset<int>> idx; //記錄節點結尾的字串id
int q[N], idn[N], mx[N];
void init() {
idx.resize(1, multiset<int>());
}
int newnode() {
idx.pb(multiset<int>());
mx[++tot] = -1;
return tot;
}
void insert(char* s, int id) {
int p = 0;
for (int i = 0; s[i]; ++i) {
int ch = s[i] - C;
if (!trie[p][ch]) trie[p][ch] = newnode();
p = trie[p][ch];
}
++cnt[p]; idn[id] = p;
idx[p].insert(0);
mx[p] = 0;
}
void build() {
int head = 0, tail = -1;
rep(i, 0, M - 1) if (trie[0][i]) q[++tail] = trie[0][i];
while (head <= tail) {
int p = q[head++];
rep(i, 0, M - 1)
if (trie[p][i])
fail[trie[p][i]] = trie[fail[p]][i], q[++tail] = trie[p][i];
else trie[p][i] = trie[fail[p]][i];
}
}
int query(char* s) {
set<int> v;
int p = 0, res = -1;
for (int i = 0; s[i]; ++i) {
p = trie[p][s[i] - C];
for (int tmp = p; tmp && !v.count(tmp); tmp = fail[tmp]) {
umax(res, mx[tmp]); v.insert(tmp);
}
}
return res;
}
void change(int id, int k, int yk) {
int p = idn[id];
idx[p].erase(idx[p].find(yk)); idx[p].insert(k);
mx[p] = *idx[p].rbegin();
}
} ac;
const int N = 3e5 + 5;
int n, m;
int a[N];
char s[N];
int main() {
IOS; cin >> n >> m; ac.init();
rep(i, 1, n) cin >> s, ac.insert(s, i);
ac.build();
rep(i, 1, m) {
int op; cin >> op;
if (op == 2) {
cin >> s;
cout << ac.query(s) << '\n';
}
else {
int k, s; cin >> k >> s;
ac.change(k, s, a[k]); a[k] = s;
}
}
return 0;
}