20250824
T1
我们惊奇地发现这题不是直接哈希加一个桶就写完了吗?顺序统计哈希,记录答案。光速打了一个出来,发现空间只有 31.25MB,算了算,好像不会超。
赛后一测发现超时了。map 换成 umap 就过了。map 万恶之源。
#include <bits/stdc++.h>
using namespace std;
using ULL = unsigned long long;
const int kN = 2e5 + 7;
const ULL base = 13331;
int n, ans;
string s;
ULL has[kN], bpow[kN];
unordered_map<ULL, bool> b;
ULL gethash(int l, int r) {
return has[r] - has[l - 1] * bpow[r - l + 1];
}
bool check(int x) {
b.clear(); ULL f = 0;
for (int i = 1; i + x - 1 <= n; i++) {
f = gethash(i, i + x - 1);
if (b.count(f)) return 1; b[f] = 1;
}
return 0;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> s, s = " " + s, bpow[0] = 1;
for (int i = 1; i <= n; i++) {
has[i] = has[i - 1] * base + s[i];
bpow[i] = bpow[i - 1] * base;
}
for (int l = 1, r = n, mid; l <= r; ) {
mid = (l + r) >> 1;
if (check(mid)) l = mid + 1, ans = mid;
else r = mid - 1;
}
cout << ans;
return 0;
}
T2
这个东西不是我上午刚出的模拟赛的 T4 吗???简直一模一样!
实际上就是考虑到等差加排列的性质:当我们建立一个桶时,如果对于数 \(i\),假设差为 \(d\),如果 \(i-d\) 存在过但 \(i+d\) 还没有出现,那么由于这是个排列,这个数一定在后面出现,那么也就一定是等差序列。因此考虑拿线段树维护一个桶,对于每个 \(i\),只要其左右不回文,那么一定找得到,线段树/树状数组维护哈希即可。
然后写出来了,大样例都过了,赛后一测,0 分???我一看,int len = min(n - a[i], a[i] - 1), Update(a[i]);,哈哈😄!
#include <bits/stdc++.h>
#define ls (p << 1)
#define rs ((p << 1) | 1)
using namespace std;
using ULL = unsigned long long;
const int kN = 5e5 + 7, base = 131;
int T, n, a[kN];
ULL bpow[kN];
struct S {
ULL has1, has2, len;
friend S operator + (S a, S b) {
return {
a.has1 * bpow[b.len] + b.has1,
b.has2 * bpow[a.len] + a.has2,
a.len + b.len
};
}
} seg[kN << 2];
void Build(int l = 1, int r = n, int p = 1) {
if (l == r) return (void)(seg[p] = {0, 0, 1});
int mid = (l + r) >> 1;
Build(l, mid, ls), Build(mid + 1, r, rs);
seg[p] = seg[ls] + seg[rs];
}
void Update(int x, int l = 1, int r = n, int p = 1) {
if (l == r) return (void)(seg[p] = {1, 1, 1});
int mid = (l + r) >> 1;
if (x <= mid) Update(x, l, mid, ls);
else Update(x, mid + 1, r, rs);
seg[p] = seg[ls] + seg[rs];
}
S Query(int s, int t, int l = 1, int r = n, int p = 1) {
if (s <= l && r <= t) return seg[p];
int mid = (l + r) >> 1; S res = {0, 0, 0};
if (s <= mid) res = res + Query(s, t, l, mid, ls);
if (mid + 1 <= t) res = res + Query(s, t, mid + 1, r, rs);
return res;
}
void Work() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
Build(1, n, 1);
for (int i = 1, len = 0; i <= n; i++) {
len = min(n - a[i], a[i] - 1), Update(a[i]);
if (len == 0) continue;
if (Query(a[i] - len, a[i] - 1).has1 != Query(a[i] + 1, a[i] + len).has2) return (void)(cout << "YES\n");
}
cout << "NO\n";
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
bpow[0] = 1;
for (int i = 1; i < kN; i++) bpow[i] = bpow[i - 1] * base;
Work();
return 0;
}
T3
考虑什么时候有无解的情况:一个串的前缀出现过,或者在按字典序建图时出现了环。
前者可以直接使用字典树,后者带一个建图,将串对 trie 建边,具体来讲,对于节点 \(i\),由于字母 \(i\) 要排在在所有儿子中最靠前的那个,因此我们对其他儿子建一条有向边,代表当前字母的优先级比其他儿子高,如果形成了环则无解,答案可以在跑拓扑排序时记录。
#include <bits/stdc++.h>
using namespace std;
const int kN = 1e6 + 7, kM = 2.5e4 + 7;
int n, m, in[kN];
string s[kM];
queue<int> q;
vector<int> g[28], ans;
struct T {
int ch[27], ed, t;
} a[kN];
int f(int c) {
return c - 'a';
}
void Insert(string s) {
int p = 0, k = 0;
for (int c : s) {
k = f(c), (a[p].ch[k] == 0) && (a[p].ch[k] = ++m), p = a[p].ch[k], a[p].t++;
}
a[p].ed++;
}
bool Find(string s) {
int p = 0, k = 0;
for (int c : s) {
k = f(c);
if (a[p].ed) return 1;
p = a[p].ch[k];
}
return 0;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> s[i], Insert(s[i]);
}
for (int i = 1; i <= n; i++) {
if (Find(s[i])) {
cout << "nemoguce\n";
continue;
}
ans.clear();
for (int j = 0; j < 26; j++) g[j].clear(), in[j] = 0;
int u = 0;
for (int j = 0; j < s[i].size(); j++) {
int c = s[i][j] - 'a';
for (int k = 0; k < 26; k++) {
if (c == k || !a[u].ch[k]) continue;
g[c].push_back(k), in[k]++;
}
u = a[u].ch[c];
}
for (int j = 0; j < 26; j++) {
if (!in[j]) q.push(j);
}
while (q.size()) {
int u = q.front(); q.pop();
ans.push_back(u + 'a');
for (int v : g[u]) {
if (!--in[v]) q.push(v);
}
}
for (int j = 0; j < 26; j++) {
if (in[j] > 0) {
cout << "nemoguce\n";
goto shit;
}
}
if (ans.size() == 26) for (char x : ans) cout << x;
else cout << "nemoguce";
cout << '\n';
shit:;
}
return 0;
}
T4
KMP + DP。

浙公网安备 33010602011771号