江西省赛补题G.Magic Number Group ——莫队

题意:

找出一个p,让这个p尽可能多得整除区间内的数,问这个p最多能整除区间内的多少个数。

思路:

把每个数分解质因数,转化成求区间众数,进而使用莫队解决。

// Decline is inevitable,
// Romance will last forever.
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
#define fi first
#define se second
#define ll long long
#define LL long long
//#define int long long
#define endl '\n'
const int maxn = 5e4 + 10;
const int maxm = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int dx[] = {0, 0, -1, 1}; //{0, 0, 1, 1, 1,-1,-1,-1}
const int dy[] = {1, -1, 0, 0}; //{1,-1, 1, 0,-1, 1, 0,-1}
const int P = 998244353;
struct Query {
    int l, r, id, pos;  //
    bool operator < (const Query &x) const {
        if(pos == x.pos) {
            if(x.pos & 1)
                return r < x.r;
            return r > x.r;
        }
        return pos < x.pos;
    }
}q[maxn];
int b[maxn], n, m;
vector<int> g[maxn];
int cnt[maxm], ans[maxn], maxx, num[maxm];  //num[i]表示当前区间内数量为i的数一共有多少个
void add(int pos) {
    for(auto i : g[pos]) {
        num[cnt[i]]--;
        cnt[i]++;
        num[cnt[i]]++;
        maxx = max(maxx, cnt[i]);
    }
}
void del(int pos) {
    for(auto i : g[pos]) {
        num[cnt[i]]--;
        if(maxx == cnt[i] && num[cnt[i]] == 0)
            maxx--;
        cnt[i]--;
        num[cnt[i]]++;
    }
}
void get_fac(int n, vector<int> &C) {  //返回值s是质因子个数 同时将相同质因子存入C
    C.clear();
    for (int i = 2; i * i <= n; i++) {
        if(n % i == 0) {
            C.push_back(i);
            while(n % i == 0) n /= i;
        }
    }
    if (n > 1) C.push_back(n);
}
void solve() {
    maxx = 0;
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> b[i];
    for(int i = 1; i <= n; i++) {
        get_fac(b[i], g[i]);
    }
    int sq = (int)sqrt(n);
    for(int i = 1; i <= m; i++) {
        cin >> q[i].l >> q[i].r;
        q[i].id = i;
        q[i].pos = (q[i].l - 1) / sq + 1;
    }
    sort(q + 1, q + m + 1);
    int l = 1, r = 0;
    for(int i = 1; i <= m; i++) {
        while(l > q[i].l)   add(--l);
        while(r < q[i].r)   add(++r);
        while(l < q[i].l)   del(l++);
        while(r > q[i].r)   del(r--);
        ans[q[i].id] = maxx;
    }
    for(int i = 1; i <= m; i++) cout << ans[i] << endl;
    while (l <= r)  del(l++);
}
signed main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T; cin >> T; while(T--)
        solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_59273843/article/details/121296967