hdu-5869 Different GCD Subarray Query gcd预处理 + 树状数组 + 离线

来源:互联网 发布:php spl 编辑:程序博客网 时间:2024/05/21 03:54

http://acm.hdu.edu.cn/showproblem.php?pid=5869


题意:

  长度n的序列, m个询问区间[L, R], 问区间内的所有子段的不同GCD值有多少种.

n,m<=1e5
又学到一个套路,预处理一个gcd表,固定右端点,向左延伸有多少个不同的gcd值以及他们出现的位置。
每固定一个端点的话,log下降的很快,不会超过logA个。

要是预处理出这个东西的话,我们把询问按照右端点离线,就又是那个套路了,bit维护一下


#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <map>#include <set>#include <vector>#include <iostream>using namespace std;const int N =1000000+50;typedef long long ll;int n,m;struct que{    int x,y,id;};bool cmp(que a,que b){    return a.y<b.y;}que qq[N];int tree[N];int ans[N];int vis[N];int aa[N];vector< pair<int,int > >mp[N];inline int lowbit(int x){    return x&-x;}void add(int x,int v){    for (int i=x;i<=n;i+=lowbit(i))    tree[i]+=v;}int get(int x){    int sum=0;    for (int i=x;i;i-=lowbit(i))        sum+=tree[i];    return sum;}void pre(){    for (int i=1; i<=n; i++)mp[i].clear();    for (int i=1; i<=n; i++)    {        int x=aa[i],y=i;        mp[i].push_back(make_pair(x,y));        for (int j=0; j<mp[i-1].size(); j++)        {            int tmp=__gcd(x,mp[i-1][j].first);            if (x!=tmp)            {                x=tmp;                y=mp[i-1][j].second;                mp[i].push_back(make_pair(x,y));            }        }    }}int main(){    while(cin>>n>>m)    {        memset(vis,0,sizeof vis);        memset(tree,0,sizeof tree);        for (int i=1; i<=n; i++)            scanf("%d",&aa[i]);        for (int i=1; i<=m; i++)            scanf("%d%d",&qq[i].x,&qq[i].y),qq[i].id=i;        pre();        sort(qq+1,qq+1+m,cmp);         int pos=1;        for (int i=1; i<=m; i++)        {            int x=qq[i].x,y=qq[i].y;            while(pos<=y)            {                for (int j=0;j<mp[pos].size();j++)                {                    int f=mp[pos][j].first,s=mp[pos][j].second;                    if (vis[f]) add(vis[f],-1);                    vis[f]=s;                    add(s,1);                }                pos++;            }            ans[qq[i].id]=get(y)-get(x-1);        }        for (int i=1; i<=m; i++)        printf("%d\n",ans[i]);     }    return 0;}


0 0
原创粉丝点击