Petals linger about
感觉很有难度啊。
这种问题,首先因为块内的差分是相等的,所以直接做差分。块间的话,我赛时理解错了,以为 \(c\) 是可变的,实际上并不是,因此差分也是对的。
先考虑怎么对于单块进行判定。
不妨假设块长为 \(h\)。则判定的条件显然为:\(|a_{h+1} - a_1| = 1\),这个等价于差分数组 \(|\sum_{i=1}^h e_i| = 1\),同时满足差分数组 \([L,R-h]=[L+h,R]\) 以及整除的条件显然也是要满足的。我们声称满足这两个条件的块长 \(h\) 为循环块长。
假设现在存在循环块长 \(x,y\),显然满足 \(x+y \le k\)。因此我们有 \(gcd(x,y)\) 同样是满足的。所以我们的最小循环块长 \(p\) 一定是合法块长。再考虑 \(|c|=1\) 的限制,我们不妨假设存在一个块长 \(mp\) 合法,由于循环,我们有 \(m \sum_{i=1}^p e_i = \sum_{i=1}^{mp} e_i\)。因此 \(m=1\) 且 \(|\sum_{i=1}^p| = 1\)。因此我们只需要找到这个 \(p\) 就行了。
考虑怎么找到这个 \(p\),显然 \(h=k\) 时合法,因此我们直接能除就除,复杂度是 \(\log\) 的。
再考虑 \(d\) 的限制。我们发现我们的代码会重复提取同一段序列,我们肯定是要优化的。因此我们对于单个 \(d\) 拆开做。
具体的,定义 \(s_d\) 表示的是公差为 \(d\) 的询问的 \(k\) 的和,如果 \(s_d \le n-d\),代表我们直接提取更优,因此直接提取。否则,代表我们直接做哈希更优,因此直接做哈希。
证明一下这个的复杂度。\(d \le \sqrt n\) 的不超过 \(\sqrt n\) 个,因此做哈希没有问题。\(d \ge \sqrt n\) 的,\(k \le \sqrt n\),因此直接做也是对的。
时间复杂度 \(O(q \sqrt n + q \log n)\)。
Code
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
#define ull unsigned long long
const int N = 1e5 + 10;
int a[N],n;
int ans[N];
struct question{
int l,r,k;
}ques[N];
vector<int> vec[N];
LL s[N];
int vis[N],pri[N],tot;
void init(){
for(int i=2;i<=N-10;i++){
if(vis[i] == 0){
vis[i] = i;
pri[++tot] = i;
}
for(int j=1;j<=tot;j++){
if(i * pri[j] > N) break;
vis[i*pri[j]] = pri[j];
if(i % pri[j] == 0) break;
}
}
return ;
}
const ull base = 1000003;
const ull base2 = 1000033;
ull pw[N],pw2[N];
ull hsh[N],hsh2[N];
ull get1(int L,int R,int len,int d){
return hsh[R] - (L - d >= 0 ? hsh[L-d] : 0) * pw[len];
}
ull get2(int L,int R,int len,int d){
return hsh2[R] - (L - d >= 0 ? hsh2[L-d] : 0) * pw2[len];
}
int main(){
IOS;
init();
cin >> n;
for(int i=1;i<=n;i++)
cin >> a[i];
pw[0] = pw2[0] = 1;
for(int i=1;i<=n;i++){
pw[i] = pw[i-1] * base;
pw2[i] = pw2[i-1] * base2;
}
int Q;
cin >> Q;
for(int i=1;i<=Q;i++){
cin >> ques[i].l >> ques[i].r >> ques[i].k;
int d = (ques[i].r - ques[i].l) / (ques[i].k - 1);
vec[d].push_back(i);
s[d] += ques[i].k;
}
for(int d=1;d<=n;d++){
if(vec[d].empty()) continue;
if(s[d] < n - d){
for(int id : vec[d]){
int L = ques[id].l,R = ques[id].r,k = ques[id].k;
int len = k - 1;
hsh[0] = hsh2[0] = 0;
for(int i=1,x=L;i<=len;i++,x+=d){
hsh[i] = hsh[i-1] * base + (a[x+d] - a[x] + n + 1);
hsh2[i] = hsh2[i-1] * base2 + (a[x+d] - a[x] + n + 1);
}
int p,tmp;p = tmp = k;
while(tmp > 1){
int x = vis[tmp];
while(tmp % x == 0){
int h = p / x;
if(k - 1 - h == 0 || get1(1,k-1-h,k-h-1,1) == get1(h+1,k-1,k-h-1,1) && get2(1,k-h-1,k-h-1,1) == get2(h+1,k-1,k-h-1,1))
p /= x;
tmp /= x;
}
}
if(p != k && abs(a[p*d+L] - a[L]) == 1)
ans[id] = 1;
else ans[id] = 0;
}
}
else{
hsh[0] = hsh2[0] = 0;
for(int i=1;i<=n-d;i++){
hsh[i] = (i > d ? hsh[i-d] : 0) * base + (a[i+d] - a[i] + n + 1);
hsh2[i] = (i > d ? hsh2[i-d] : 0) * base2 + (a[i+d] - a[i] + n + 1);
}
for(int id : vec[d]){
int L = ques[id].l,R = ques[id].r,k = ques[id].k;
int len = k - 1;
int p,tmp;p = tmp = k;
while(tmp > 1){
int x = vis[tmp];
while(tmp % x == 0){
int h = p / x;
if(k - 1 - h == 0 || get1(L,R-(h+1)*d,k-h-1,d) == get1(L+h*d,R-d,k-h-1,d) && get2(L,R-(h+1)*d,k-h-1,d) == get2(L+h*d,R-d,k-h-1,d))
p /= x;
tmp /= x;
}
}
if(p != k && abs(a[p*d+L] - a[L]) == 1)
ans[id] = 1;
else ans[id] = 0;
}
}
}
for(int i=1;i<=Q;i++){
if(ans[i]) cout << "Yes\n";
else cout << "No\n";
}
return 0;
}

浙公网安备 33010602011771号