A
在 l ~ r 之间肯定不行
当 a > r, 则 l >= a/2 即 r < a <= 2l, 即 r < 2l
当 a < l, 则 (lfloor frac{r}{lfloor frac{a}{2} floor} floor - lfloor frac{l-1}{lfloor frac{a}{2} floor} floor ≡ 0), 即 r - l + 1 < a / 2 即 2r - 2l + 2 < a < l
即 2r - 2l + 2 + 1 < l 即 (frac{2}{3})r + 1 < l 即 (frac{1}{3})r < a/2 然而 a < l <= r 故 a < l 命题错误
int main() {
IOS;
for (cin >> _; _; --_) {
ll a, b; cin >> a >> b;
if (a * 2 > b) cout << "YES
";
else cout << "NO
";
}
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 << '
';
}
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] << '
';
}
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] << '
';
}
return 0;
}
E
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) << '
';
}
else {
int k, s; cin >> k >> s;
ac.change(k, s, a[k]); a[k] = s;
}
}
return 0;
}