2021ICPC江西省赛G.Magic Number Group莫队
Posted hesorchen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021ICPC江西省赛G.Magic Number Group莫队相关的知识,希望对你有一定的参考价值。
题目
给定一个正整数序列,每次询问区间 [ L , R ] [L,R] [L,R],任意选择一个大于1的正整数p,该区间内最多有多少数能被p整除。
解题思路
对于p,我们一定是选择一个质数,问题就转化成了区间 [ L , R ] [L,R] [L,R],要使尽可能多的数包含质因子p。
考虑对于所有数都分解出所有质因子。每个数的质因子数量很少,最后就是莫队离线维护众数板子。
代码
#include <bits/stdc++.h>
using namespace std;
const int M = 1e6 + 6;
vector<int> fac[M];
bool vis[M];
void init() //预处理每个数的质因子
{
for (int i = 2; i < M; i++)
{
if (!vis[i])
{
for (int j = i; j < M; j += i)
{
vis[j] = 1;
fac[j].emplace_back(i);
}
}
}
}
const int N = 5e4 + 5;
vector<int> a(N);
int block;
struct node
{
int l, r, id;
bool operator<(const node &o) const
{
if (l / block != o.l / block)
return l < o.l;
if (l / block & 1)
return r > o.r;
return r < o.r;
}
} q[N];
int cnt[M];
int num[M];
vector<int> ans(N);
int maxx;
void del(int x)
{
for (auto p : fac[a[x]])
{
num[cnt[p]]--;
if (maxx == cnt[p] && num[cnt[p]] == 0)
maxx--;
cnt[p]--;
num[cnt[p]]++;
}
}
void add(int x)
{
for (auto p : fac[a[x]])
{
num[cnt[p]]--;
cnt[p]++;
num[cnt[p]]++;
maxx = max(maxx, cnt[p]);
}
}
int main()
{
init();
int t;
scanf("%d", &t);
while (t--)
{
int n, m;
maxx = 0;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
block = sqrt(n);
for (int i = 1; i <= m; ++i)
{
scanf("%d %d", &q[i].l, &q[i].r);
q[i].id = i;
}
sort(q + 1, q + 1 + m);
int l = 1, r = 0;
for (int i = 1; i <= m; ++i)
{
while (l < q[i].l)
del(l++);
while (l > q[i].l)
add(--l);
while (r < q[i].r)
add(++r);
while (r > q[i].r)
del(r--);
ans[q[i].id] = maxx;
}
for (int i = 1; i <= m; ++i)
printf("%d\\n", ans[i]);
while (l <= r) //清空
del(l++);
}
return 0;
}
以上是关于2021ICPC江西省赛G.Magic Number Group莫队的主要内容,如果未能解决你的问题,请参考以下文章