HDU 5869 Different GCD Subarray Query (离线处理 树状数组)

来源:互联网 发布:大数据需要学哪些技术 编辑:程序博客网 时间:2024/05/21 03:17

题意:给你一个长度为n的数组,q次询问区间[L, R], 求区间内的所有子段的不同gcd值有多少种.


思路:有个知识:固定一个数为右端点,区间所能形成的gcd最多有logn个。所以可以预处理出每个数为右端点所能形

的gcd,相同gcd取左端点靠右的。这样对询问的R排序就能离线处理,用树状数组维护即可。


代码:

#include<bits/stdc++.h>using namespace std;const int maxn = 1e6+15;int n, q, tree[maxn];int a[maxn], ans[maxn], vis[maxn];typedef pair<int, int> pp;vector<pp> g[maxn];struct node{    int l, r, id;    bool operator < (const node &a) const    {        if(r == a.r) return l < a.l;        return r < a.r;    }}qq[maxn];int lowbit(int x){    return x&(-x);}void update(int pos, int val){    while(pos < maxn)    {        tree[pos] += val;        pos += lowbit(pos);    }}int query(int pos){    int res = 0;    while(pos)    {        res += tree[pos];        pos -= lowbit(pos);    }    return res;}void solve(){    for(int i = 1; i <= n; i++)    {        g[i].push_back(pp(a[i], i));        int pre = a[i];        for(int j = 0; j < g[i-1].size(); j++)        {            int tmp = __gcd(a[i], g[i-1][j].first);            if(tmp != pre)                g[i].push_back(pp(tmp, g[i-1][j].second)), pre = tmp;        }    }    int cur = 0;    for(int i = 1; i <= q; i++)    {        while(cur < qq[i].r)        {            cur++;            for(int j = 0; j < g[cur].size(); j++)            {                int tmp = g[cur][j].first;                int pos = g[cur][j].second;                if(vis[tmp]) update(vis[tmp], -1);                vis[tmp] = pos;                update(vis[tmp], 1);            }        }        ans[qq[i].id] = query(qq[i].r)-query(qq[i].l-1);    }    for(int i = 1; i <= q; i++)        printf("%d\n", ans[i]);}int main(void){    while(cin >> n >> q)    {        memset(vis, 0, sizeof(vis));        memset(tree, 0, sizeof(tree));        for(int i = 0; i <= n; i++)            g[i].clear();        for(int i = 1; i <= n; i++)            scanf("%d", &a[i]);        for(int i = 1; i <= q; i++)            scanf("%d%d", &qq[i].l, &qq[i].r), qq[i].id = i;        sort(qq+1, qq+1+q);        solve();    }    return 0;}


阅读全文
1 0
原创粉丝点击