zoukankan      html  css  js  c++  java
  • HDU 5869区间CGD不同种类数---树状数组+map统计区间不同种类数(离线)

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

    题意:已知一个数组,Q个查询,问你区间子区间的不同GCD种类数

    思路:先考虑一个数组区间不同个数,可以使用离线的树状数组实现,具体是对查询右端点进行排序,依次转移解决问题。

    首先我们考虑固定右端点的查询区间不同数字,其实我们可以在每个数字出现的最右位置记录一下就可以了,统计起来就是sum[r]-sum[l]

    这样子考虑右区间移动,就要改变那个数的最右位置,显然可以用一个map来维护每个数字出现的最右位置。

    回到这个题目,显然一个点不只是一个数字,我们按照之前多校的一个处理方法,处理出来每个点作为右端点的子区间的GCD值(套路,而且一个点的不会很多,大致logAi个,用一个vector数组维护爽一下),这样子每个点就是一个数组了,但是统计的时候又不是区间所有点数组的不同数字个数,但是也很好魔改,其实我们只需要每个GCD出现的最右距离就可以了,因为如果查询的L在这个L左面,自然会被算进去,如果不在,那么就无视,以后的查询可能会需要,还是继续用map维护就好了。

    所以这道题就解决啦!关键还是学会树状数组加map来统计区间不同种类数的方法。

    代码:

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <map>
    #include <vector>
    using namespace std;
    #define MAX 100005
    const int INF=1e9+7;
    int n,m;
    int a[MAX];
    int b[MAX];
    int ans[MAX];
    struct Q{
        int r,l,id;
    }q[MAX];
    vector<pair<int,int> > G[MAX];
    map<int,int> H;
    
    int lowbit(int x){
        return x & (-x);
    }
    
    void modify(int x,int add){
        while(x<=MAX){
            b[x]+=add;
            x+=lowbit(x);
        }
    }
    
    int get_sum(int x){
        int ret=0;
        while(x!=0){
            ret+=b[x];
            x-=lowbit(x);
        }
        return ret;
    }
    
    int gcd(int a,int b){
        return b==0?a:gcd(b,a%b);
    }
    
    bool cmp(const Q &q1,const Q &q2){
        if(q1.r!=q2.r)
        return q1.r<q2.r;
        else return q1.id<q2.id;
    }
    
    void F(int x){
        G[x].push_back(make_pair(a[x],x));
        int cnt=0;
        for(int i=0;i<G[x-1].size();i++){
            int gc=gcd(G[x-1][i].first,a[x]);
            if(gc!=G[x][cnt].first){
                G[x].push_back(make_pair(gc,G[x-1][i].second));
                cnt++;
            }
            else{
               // G[x][cnt].second=G[x-1][i].second;
            }
        }
    }
    
    void init(){
        for(int i=0;i<=n;i++) G[i].clear();
        H.clear();
        memset(b,0,sizeof(b));
        G[1].push_back(make_pair(a[1],1));
        for(int i=2;i<=n;i++) F(i);
    }
    
    int main(){
        int t;
        while (scanf("%d%d",&n,&m)!=EOF){
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            init();
            int l,r;
            for(int i=0;i<m;i++){
                scanf("%d%d",&q[i].l,&q[i].r);
                q[i].id=i;
            }
            sort(q,q+m,cmp);
            int R=1;
            for(int i=0;i<m;i++){
                while(R<=q[i].r){
                    for(int j=0;j<G[R].size();j++){
                        if(H.count(G[R][j].first)!=0){
                            modify(H[G[R][j].first],-1);
                        }
                        H[G[R][j].first]=G[R][j].second;
                        modify(G[R][j].second,1);
                    }
                    R++;
                }
                ans[q[i].id]=get_sum(q[i].r)-get_sum(q[i].l-1);
            }
            for(int i=0;i<m;i++) printf("%d
    ",ans[i]);
    
        }
        return 0;
    }



  • 相关阅读:
    IFS二次开发03——Item
    TFS二次开发01——TeamProjectsPicher
    我的八年程序之路(二)三月方便面换来800月薪
    我的八年程序之路(一)求职的艰辛
    重温CSS之背景、文本样式
    重温CSS之文档结构
    重温CSS之基础
    不使用第三方软件、使用IE11自带功能来屏蔽浏览器广告
    Windwos8.1下配置PHP环境
    Python学习系列之(二)图解Windows8.1下安装Django
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672539.html
Copyright © 2011-2022 走看看