有一個小失誤,WA了很久。
轉移的順序應該是
①增加r
②減少l
③減少r
④增加l
否則可能會出現錯誤
比如想從[a,b]轉移到[c,d]
但是c<a,d<b,d<a
如果順序不對的話,按照我自己的算法,就會算錯。
代碼
#include<stdio.h>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 10010;
int n,Q;
int A[maxn];
int b[maxn];
vector<int>l[maxn][2];
vector<int>r[maxn][2];
vector<int>vec[2];
struct qr
{
int l,r;
int id;
ll ans;
}QR[maxn];
bool cmp1(qr x,qr y)
{
if(b[x.l]!=b[y.l]) return b[x.l]<b[y.l];
else return x.r<y.r;
}
bool cmp2(qr x,qr y)
{
return x.id<y.id;
}
void read()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",A+i);
for(int j=0;j<2;j++)
{
l[i][j].clear();
r[i][j].clear();
}
}
scanf("%d",&Q);
b[0]=sqrt(n);
for(int i=1;i<=Q;i++)
{
scanf("%d %d",&QR[i].l,&QR[i].r);
QR[i].id=i;
b[i]=(i-1)/b[0]+1;
}
}
int gcd(int a,int b)
{
return !b?a:gcd(b,a%b);
}
void erase(int p)
{
for(int i=p;i<(int)vec[0].size()-1;i++)
for(int j=0;j<2;j++)
vec[j][i]=vec[j][i+1];
for(int j=0;j<2;j++)
vec[j].resize(vec[j].size()-1);
}
void insert(int x,int y)
{
for(int i=0;i<(int)vec[0].size();i++)
if(vec[0][i]==x)
{
erase(i);
break;
}
for(int j=0;j<2;j++)
vec[j].resize(vec[j].size()+1);
for(int i=vec[0].size()-2;i>=0;i--)
for(int j=0;j<2;j++)
vec[j][i+1]=vec[j][i];
vec[0][0]=x;
vec[1][0]=y;
int GCD = vec[0][0];
for(int i=1;i<(int)vec[0].size();i++)
{
GCD = gcd(GCD,vec[0][i]);
if(GCD==1)
{
for(int j=0;j<2;j++)
vec[j].resize(i+1);
break;
}
}
}
void print()
{
puts("---");
for(int i=0;i<(int)vec[0].size();i++)
printf("%d\n",vec[0][i]);
puts("---");
}
void pre()
{
vec[0].clear();
vec[1].clear();
for(int i=1;i<=n;i++)
{
int cur=i;
int CUR=A[i];
//print();
for(int j=0;j<(int)vec[0].size();j++)
{
int VAL = vec[0][j];
int POS = vec[1][j];
VAL = gcd(VAL,CUR);
if(CUR!=VAL)
{
CUR=VAL;
cur=POS;
l[i][0].push_back(CUR);
l[i][1].push_back(cur);
}
}
insert(A[i],i);
}
vec[0].clear();
vec[1].clear();
for(int i=n;i>=1;i--)
{
int cur=i;
int CUR=A[i];
for(int j=0;j<(int)vec[0].size();j++)
{
int VAL = vec[0][j];
int POS = vec[1][j];
VAL = gcd(VAL,CUR);
if(CUR!=VAL)
{
CUR=VAL;
cur=POS;
r[i][0].push_back(CUR);
r[i][1].push_back(cur);
}
}
insert(A[i],i);
}
}
void solve()
{
read();
pre();
int le=1;
int ri=0;
ll ans=0;
sort(QR+1,QR+1+Q,cmp1);
for(int i=1;i<=Q;i++)
{
while(ri<QR[i].r)
{
ri++;
int cur=ri;
int CUR=A[ri];
for(int j=0;j<(int)l[ri][0].size();j++)
{
int VAL = l[ri][0][j];
int POS = l[ri][1][j];
ans+=1ll*min(cur-POS,cur-le+1)*CUR;
CUR=VAL;
cur=POS;
if(cur<le) break;
}
if(cur>=le) ans+=1ll*(cur-le+1)*CUR;
}
while(le>QR[i].l)
{
le--;
int cur=le;
int CUR=A[le];
for(int j=0;j<(int)r[le][0].size();j++)
{
int VAL = r[le][0][j];
int POS = r[le][1][j];
ans+=1ll*min(POS-cur,ri-cur+1)*CUR;
CUR=VAL;
cur=POS;
if(cur>ri) break;
}
if(cur<=ri) ans+=1ll*(ri-cur+1)*CUR;
}
while(ri>QR[i].r)
{
int cur=ri;
int CUR=A[ri];
for(int j=0;j<(int)l[ri][0].size();j++)
{
int VAL = l[ri][0][j];
int POS = l[ri][1][j];
ans-=1ll*min(cur-POS,cur-le+1)*CUR;
CUR=VAL;
cur=POS;
if(cur<le) break;
}
if(cur>=le) ans-=1ll*(cur-le+1)*CUR;
ri--;
}
while(le<QR[i].l)
{
int cur=le;
int CUR=A[le];
for(int j=0;j<(int)r[le][0].size();j++)
{
int VAL = r[le][0][j];
int POS = r[le][1][j];
ans-=1ll*min(POS-cur,ri-cur+1)*CUR;
CUR=VAL;
cur=POS;
if(cur>ri) break;
}
if(cur<=ri) ans-=1ll*(ri-cur+1)*CUR;
le++;
}
QR[i].ans=ans;
}
sort(QR+1,QR+1+Q,cmp2);
for(int i=1;i<=Q;i++)
printf("%lld\n",QR[i].ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}