题目链接:https://ac.nowcoder.com/acm/contest/4090/E
题目大意:
思路:我们可以证明一定是一个区间里面的a[i]与X。你们问题就转化成给你一个区间[L, R]找到一个L<=i<=R。最大化gcd(a[i], X)。因为最大GCD一定是X的因数。可以直接莫队维护一个区间%P的个数。
题解思路:
//莫队
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int a[100005], f[100005], ans[100005];
int pos[100005];
vector<int> v[100005];
vector<int> qu[100005];
struct Q{
int l, r, x, i;
}q[100005];
void add(int x){
for(auto u: v[x]){
f[u]++;
}
}
void del(int x){
for(auto u: v[x]){
f[u]--;
}
}
int main(){
int n, m;scanf("%d%d", &n, &m);
int Len=sqrt(n);
for(int i=1; i<=n; i++){
pos[i]=i/Len;
scanf("%d", &a[i]);
for(int j=1; j*j<=a[i]; j++){
if(a[i]%j==0){
v[i].push_back(j);
if(j!=a[i]/j){
v[i].push_back(a[i]/j);
}
}
}
}
for(int i=1; i<=m; i++){
int l, r, x;
scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].x);
for(int j=1; j*j<=q[i].x; j++){
if(q[i].x%j==0){
qu[i].push_back(j);
if(j!=q[i].x/j){
qu[i].push_back(q[i].x/j);
}
}
}
sort(qu[i].begin(), qu[i].end(), greater<int>() );
q[i].i=i;
}
sort(q+1, q+1+m, [](Q a, Q b){return pos[a.l]==pos[b.l]?(pos[a.l]&1)?a.r<b.r:a.r>b.r:pos[a.l]<pos[b.l];});
int L=1, R=0;
for(int i=1;i<=m;i++)
{
while(L<q[i].l)
{
del(L);
L++;
}
while(L>q[i].l)
{
L--;
add(L);
}
while(R<q[i].r)
{
R++;
add(R);
}
while(R>q[i].r)
{
del(R);
R--;
}
for(auto u: qu[q[i].i]){
if(f[u]){
ans[q[i].i]=u;
break;
}
}
}
for(int i=1;i<=m;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}
//离线-区间处理
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int a[100005], ans[100005];
struct node{
int l, r, i;
bool operator<(const node &a) const{
return r<a.r;
}
};
vector<int> v[100005];
vector<node> q[100005];
int main(){
int n, m;scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++){
scanf("%d", &a[i]);
for(int j=1; j*j<=a[i]; j++){
if(a[i]%j==0){
v[j].push_back(i);
if(j!=a[i]/j){
v[a[i]/j].push_back(i);
}
}
}
}
for(int i=1; i<=m; i++){
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
for(int j=1; j*j<=x; j++){
if(x%j==0){
q[j].push_back(node{l, r, i});
if(j!=x/j){
q[x/j].push_back(node{l, r, i});
}
}
}
}
for(int i=1; i<=100000; i++){
if(!v[i].size()){
continue;
}
int k=0;
sort(q[i].begin(), q[i].end());
while(k<q[i].size()&&q[i][k].r<v[i][0]) k++;
for(int j=0; j<v[i].size()-1; j++){
while(k<q[i].size()&&q[i][k].r<v[i][j+1]){
if(q[i][k].l<=v[i][j]){
ans[q[i][k].i]=max(ans[q[i][k].i], i);
}
k++;
}
}
while(k<q[i].size()){
if(q[i][k].l<=v[i][v[i].size()-1])
ans[q[i][k].i]=max(ans[q[i][k].i],i);
k++;
}
}
for(int i=1;i<=m;i++){
printf("%d\n",ans[i]);
}
return 0;
}