链接:https://codeforces.com/contest/1549/problem/D
题意:
给出n个数的序列,要求找出一段连续的子序列,满足每个数模m的余数相同。
输出子序列最长长度
题解:
每个数模m余数相同 可以转化成 两个数之差模m为0
进而得知满足条件的子序列,其两两差值的gcd一定大于1
用线段树维护区间gcd
然后用长度不减的滑动窗口从左到右扫一遍,每找到当前长度的答案就使窗口的长度增加1
注意!有大坑,当n等于1时无法构造b数组,线段树l=1,r=0,会出问题
必须特判掉1
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
ll t[maxn*4];
ll a[maxn];
ll b[maxn];
void pushup(int rt){
t[rt]=__gcd(t[rt<<1],t[rt<<1|1]);
return;
}
void build(int l,int r,int rt){
if(l==r){
t[rt]=b[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
return;
}
ll query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return t[rt];
}
int mid=(l+r)>>1;
ll ans=0;
if(mid>=L){
ans=query(L,R,l,mid,rt<<1);
}
if(mid<R){
if(!ans){
ans=query(L,R,mid+1,r,rt<<1|1);
}else{
ans=__gcd(ans,query(L,R,mid+1,r,rt<<1|1));
}
}
return ans;
}
void solve(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
if(i){
b[i]=abs(a[i]-a[i-1]);
}
}
if(n==1){
cout<<1<<endl;
return;
}
build(1,n-1,1);
int ans=1;
int l=1;
int r=1;
while(r<n){
if(query(l,r,1,n-1,1)>1){
ans++;
r++;
}else{
l++;
r++;
}
}
cout<<ans<<endl;
return;
}
int main(){
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
solve();
}
//system("pause");
return 0;
}