我再也不用 set 了
2025-08-17 11:00:53
发布于:浙江
题目:给定两个长度分别为 的数组 。
对于任意两个长度相等的数组 ,定义函数 如下:
生成一个数列 ,使 。如果 是回文数列,则 ,否则 。
请你求出最大的 ,使得存在 分别长度为 的子数组 ,使 。
好的,我们遇到题先看部分分:
对于所有数据,。
好的,注意到没有部分分。这启发我们直接想正解。
有一个结论:如果存在一个数 符合要求,则 也符合这个要求。因为只需要让 删除最左边和最右边的数即可。但 就不一定符合要求了,比如这里有一个 hack(我才不会告诉你这是样例):
5 6
4 3 3 2 1
4 1 5 1 3 2
显然当 可以使 ,但不存在 的情况使得存在子数组满足条件。
考虑奇偶分开二分,选择长度最大值。
现在的问题是:如何以 左右的时间复杂度是否存在判断长度为 的数使得子数组满足条件?
注意到 非常小,故考虑字符串哈希。
我们又注意到当长度为 的数组 为回文数组时,,其中 为任意正整数。所以我们可以通过这个特殊性质来判断,我们记录每个长度为 的子数组的正反哈希值之差,然后 查找即可。时间复杂度 。由于 ,而且奇偶分开二分本身带了 的常数,所以就不能使用大常数的 map
set
了,应该使用排序二分代替。
如果你用 set
,
还有,不能用单模哈希,冲突概率巨大,随机生成两个 的数组它会说最长的 ,但真正的答案在 左右!
#include <iostream>
#include <cstdio>
#include <vector>
#include <random>
#include <ctime>
#include <algorithm>
#define int long long
using namespace std;
mt19937 rng;
int a[100005], b[100005];
int n, m;
int inv(int n, int mod){
int t = mod - 2, ans = 1;
while(t){
if(t & 1) ans = ans * n % mod;
n = n * n % mod, t >>= 1;
}
return ans;
}
struct hashhh{
int Hsha1[100005], Hsha2[100005];
int Hshb1[100005], Hshb2[100005];
int ksm[100005], ksminv[100005];
int mul, mod;
void init(int mul, int mod){
this -> mul = mul, this -> mod = mod;
ksm[0] = 1;
ksminv[0] = 1;
ksminv[1] = inv(mul, mod);
for(int i = 1; i <= 100000; i++) ksm[i] = ksm[i - 1] * mul % mod;
for(int i = 1; i <= 100000; i++){
ksminv[i] = ksminv[i - 1] * ksminv[1] % mod;
}
for(int i = 1; i <= n; i++){
Hsha1[i] = (Hsha1[i - 1] * mul + a[i]) % mod;
Hsha2[i] = (Hsha2[i - 1] + a[i] * ksm[i - 1]) % mod;
}
for(int i = 1; i <= m; i++){
Hshb1[i] = (Hshb1[i - 1] * mul + b[i]) % mod;
Hshb2[i] = (Hshb2[i - 1] + b[i] * ksm[i - 1]) % mod;
}
}
int get(int n, int i, int val){
if(n == 1) return ((Hsha1[i] - Hsha1[i - val] * ksm[val]) % mod + mod) % mod;
if(n == 2) return ((Hsha2[i] - Hsha2[i - val]) % mod + mod) % mod * ksminv[i - val] % mod;
if(n == 3) return ((Hshb1[i] - Hshb1[i - val] * ksm[val]) % mod + mod) % mod;
if(n == 4) return ((Hshb2[i] - Hshb2[i - val]) % mod + mod) % mod * ksminv[i - val] % mod;
}
}test1, test2, test3;
int func(int hsh1, int hsh2, int mod){
return ((hsh1 - hsh2) % mod + mod) % mod;
}
bool check(int val){
vector <pair <pair <int, int>, int>> v;
for(int i = val; i <= n; i++){
int hsh11 = test1.get(1, i, val);
int hsh12 = test1.get(2, i, val);
int hsh21 = test2.get(1, i, val);
int hsh22 = test2.get(2, i, val);
int hsh31 = test3.get(1, i, val);
int hsh32 = test3.get(2, i, val);
v.push_back({{func(hsh11, hsh12, test1.mod), func(hsh21, hsh22, test2.mod)}, func(hsh31, hsh32, test3.mod)});
}
sort(v.begin(), v.end());
for(int i = val; i <= m; i++){
int hsh11 = test1.get(4, i, val);
int hsh12 = test1.get(3, i, val);
int hsh21 = test2.get(4, i, val);
int hsh22 = test2.get(3, i, val);
int hsh31 = test3.get(4, i, val);
int hsh32 = test3.get(3, i, val);
pair <pair <int, int>, int> tmp = {{func(hsh11, hsh12, test1.mod), func(hsh21, hsh22, test2.mod)}, func(hsh31, hsh32, test3.mod)};
if((*lower_bound(v.begin(), v.end(), tmp)) == tmp) return 1;
}
return 0;
}
signed main(){
freopen("palindrome.in", "r", stdin);
freopen("palindrome.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
rng.seed(time(0));
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= m; i++) cin >> b[i];
test1.init(rng() % (998244352 / 2) + (998244352 / 2), 998244353);
test2.init(rng() % (1000000006 / 2) + (1000000006 / 2), 1000000007);
test3.init(rng() % (1000002 / 2) + (1000002 / 2), 1000003);
int l = 1, r = min(n, m);
while(l <= r){
int mid = l + r >> 1;
int tmp = mid * 2 - 1;
if(tmp <= min(n, m) && check(tmp)) l = mid + 1;
else r = mid - 1;
}
int ans = r * 2 - 1;
l = 1, r = min(n, m);
while(l <= r){
int mid = l + r >> 1;
int tmp = mid * 2;
if(tmp <= min(n, m) && check(tmp)) l = mid + 1;
else r = mid - 1;
}
ans = max(ans, r * 2);
cout << ans << '\n';
cout.flush();
fclose(stdin);
fclose(stdout);
return 0;
}
时间复杂度 。
全部评论 11
时团还是太会取标题了,
学新闻学的2025-08-17 来自 浙江
1(((
2025-08-17 来自 浙江
0
这件事告诉了我们什么,不要盲目相信ACGO评测机
2025-08-16 来自 浙江
1orz
2025-08-17 来自 北京
0摸摸摸
2025-08-17 来自 浙江
0
d
2025-08-17 来自 广东
0d
2025-08-17 来自 广东
0d
2025-08-17 来自 广东
0沙发bs
2025-08-17 来自 广东
0d
2025-08-17 来自 浙江
0d
2025-08-16 来自 浙江
0怎么没人看啊
2025-08-16 来自 重庆
0d
2025-08-16 来自 浙江
0b
2025-08-16 来自 重庆
0
有帮助,赞一个