题解:P11753 [COCI 2024/2025 #5] 塔楼 / Tornjevi
P11753 [COCI 2024/2025 #5] 塔楼 / Tornjevi
一个区间的
所以可以尝试用
然后每次分别二分最左能到达哪里和最右能到哪里,显然最优左,右端点求解时互不影响。可以分别求出(即可以一次只求左,另一次只求右),然后合并为答案。
遍历
#include<bits/stdc++.h>
using namespace std;
#define MAXN 1000010
int g[MAXN][21],n,b[MAXN];
int ansl[MAXN],ansr[MAXN];
int gcd(int x,int y)
{
return (y==0?x:gcd(y,x%y));
}
void init()
{
for(int j=1;j<20;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
g[i][j]=gcd(g[i][j-1],g[i+(1<<(j-1))][j-1]);
}
int query(int l,int r)
{
int k=b[r-l+1];
return gcd(g[l][k],g[r-(1<<k)+1][k]);
}
int ask(int x,int b)
{
int l=1,r=b==1?x-1:n-x,ans=0;
while(l<=r){
int mid=(l+r)/2;
int now=(b==1?query(x-mid,x):query(x,x+mid));
if(g[x][0]==now)
ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int main(){
scanf("%d",&n);
for(int i=2;i<=1e6;i++)
b[i]=b[i/2]+1;
for(int i=1;i<=n;i++)
scanf("%d",&g[i][0]);
init();
for(int i=n;i>=1;i--)
ansl[i]=i-ask(i,1),
ansr[i]=i+ask(i,2);
for(int i=1;i<=n;i++)
printf("%d ",ansr[i]-ansl[i]+1);
return 0;
}