P3889 的分块做法
来写一下这道题的
首先一次询问
首先明确一次询问可以将序列划分为这种形状(某些部分可能不存在)。
由于是计算
不过在此之前,还需要做一些准备工作,比如求出每个数的因数,这是
中散对左块
注意到散块的大小是
我们把这个询问存在
最后我们从小到大枚举
在枚举完
中整对左块
首先预处理出每个块包含了哪些因数。这是
类似于上一个从小到大枚举
实现细节
注意到离线存询问总是存一段连续的区间,所以实际上并没有单点拆开的必要。
预处理每个块包含的因数可以用 bitset 而不是用 bool 数组存,这样会快一点。但是这道题本来也不卡常。
//Private Eye,dancing with the wind.
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
const int block=317,maxn=100000;
int n,m,a[MAXN],b[MAXN],L[MAXN],R[MAXN];
vector<int> st[MAXN];
bitset<MAXN> ts[block+5];
inline void init()
{
for(int i=1;i<=maxn;i++)
for(int j=i;j<=maxn;j+=i)
st[j].emplace_back(i);
for(int i=1;i<=n;i++)
for(int x:st[a[i]])
ts[b[i]][x]=1;
}
struct query{
int l,r,id;
query(int l_,int r_,int id_):
l(l_),r(r_),id(id_){}
};
vector<query> ql[MAXN],qL[MAXN],qr[MAXN],qR[MAXN];
int ans[MAXN],ans1[MAXN],ans2[MAXN];
bitset<MAXN> vis;
inline void solve()
{
for(int i=1;i<=n;i++)
{
if(!vis[a[i]])
{
for(int x:st[a[i]])
if(!vis[x])
{
vis[x]=1;
for(int y=x;y<=maxn;y+=x)
ans1[y]=max(ans1[y],x);
for(int j=b[i]+1;j<=b[n];j++)
if(ts[j][x]) ans2[j]=max(ans2[j],x);
}
}
for(query x:ql[i])
for(int j=x.l;j<=x.r;j++)
ans[x.id]=max(ans[x.id],ans1[a[j]]);
for(query x:qL[i])
for(int j=x.l;j<=x.r;j++)
ans[x.id]=max(ans[x.id],ans2[j]);
}
vis.reset();
memset(ans1,0,sizeof(ans1));
memset(ans2,0,sizeof(ans2));
for(int i=n;i>=1;i--)
{
if(!vis[a[i]])
{
for(int x:st[a[i]])
if(!vis[x])
{
vis[x]=1;
for(int y=x;y<=maxn;y+=x)
ans1[y]=max(ans1[y],x);
for(int j=b[i]-1;j>=1;j--)
if(ts[j][x]) ans2[j]=max(ans2[j],x);
}
}
for(query x:qr[i])
for(int j=x.l;j<=x.r;j++)
ans[x.id]=max(ans[x.id],ans1[a[j]]);
for(query x:qR[i])
for(int j=x.l;j<=x.r;j++)
ans[x.id]=max(ans[x.id],ans2[j]);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=(i-1)/block+1;
for(int i=1;i<=b[n];i++) L[i]=R[i-1]+1,R[i]=min(L[i]+block-1,n);
init(),scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
if(b[l]==b[r])
{
ql[l-1].emplace_back(query(l,r,i));
qr[r+1].emplace_back(query(l,r,i));
}
else
{
ql[l-1].emplace_back(query(l,R[b[l]],i));
ql[l-1].emplace_back(query(L[b[r]],r,i));
if(b[l]+1!=b[r]) qL[l-1].emplace_back(query(b[l]+1,b[r]-1,i));
qr[r+1].emplace_back(query(l,R[b[l]],i));
qr[r+1].emplace_back(query(L[b[r]],r,i));
if(b[l]+1!=b[r]) qR[r+1].emplace_back(query(b[l]+1,b[r]-1,i));
}
}
solve();
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}