zoukankan      html  css  js  c++  java
  • HDU 5869 Different GCD Subarray Query

    原题链接:HDU-5869

    题意为给定一组数和一组询问,每个询问用一个区间表示,要求输出区间内所有连续子序列的不同gcd值。

    这道题和HDU-3333非常像。区别在于这里需要处理的是gcd。而gcd有一个性质,即相同起点的序列的gcd非严格递减。

    对比HDU-3333,这道题需要使每个gcd对应序列的左起点尽量向右。

    扫描到位置i的时候,可以新得到的gcd只与前面的i-1个数有关,但事实上能产生的新gcd是有限的,大概有( log a_i )个。所以用gcds[][]存起来,每次用gcd[i-1]更新gcd[i]即可。

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 #define MAXN 100010
     6 #define MAXM 100010
     7 
     8 int gcd(int a,int b)
     9 {
    10     if(b==0) return a;
    11     return gcd(b,a%b);
    12 }
    13 int d[MAXN];
    14 int n,m;
    15 vector<pair<int,int> > q[MAXM];
    16 vector<pair<int,int> > gcds[MAXN];
    17 int vis[1000010];
    18 int ans[MAXM];
    19 int tree[MAXN];
    20 int lowbit(int x)
    21 {
    22     return x&(-x);
    23 }
    24 void add(int k,int num)
    25 {
    26     while(k<=n)
    27     {
    28         tree[k]+=num;
    29         k+=lowbit(k);
    30     }
    31 }
    32 int sum(int k)
    33 {
    34     int ans=0;
    35     while(k)
    36     {
    37         ans+=tree[k];
    38         k-=lowbit(k);
    39     }
    40     return ans;
    41 }
    42 int main()
    43 {
    44 #ifdef LOCAL
    45     freopen("in.txt","r",stdin);
    46 #endif
    47     while(scanf("%d%d",&n,&m)!=EOF)
    48     {
    49         for(int i=0;i<=n;i++) gcds[i].clear();
    50         for(int i=1;i<=n;i++) q[i].clear();
    51         memset(vis,0,sizeof(vis));
    52         memset(tree,0,sizeof(tree));
    53         for(int i=1;i<=n;i++) scanf("%d",&d[i]);
    54         for(int i=1;i<=m;i++)
    55         {
    56             int l,r;
    57             scanf("%d%d",&l,&r);
    58             q[r].push_back(make_pair(l,i));
    59         }
    60         for(int i=1;i<=n;i++)
    61         {
    62             if(vis[d[i]]) add(vis[d[i]],-1);
    63             add(i,1);
    64             vis[d[i]]=i;
    65             gcds[i].push_back(make_pair(d[i],i));
    66             for(unsigned int j=0;j<gcds[(i-1)].size();j++)
    67             {
    68                 int tmp1=gcd(gcds[(i-1)][j].first,d[i]),tmp2=gcds[(i-1)][j].second;
    69                 if(tmp1==gcds[i][gcds[i].size()-1].first) continue;
    70                 if(vis[tmp1]) add(vis[tmp1],-1);
    71                 add(tmp2,1);
    72                 vis[tmp1]=tmp2;
    73                 gcds[i].push_back(make_pair(tmp1,tmp2));
    74             }
    75             for(unsigned int j=0;j<q[i].size();j++)
    76             {
    77                 int tmp=q[i][j].second;
    78                 ans[tmp]=sum(i)-sum(q[i][j].first-1);
    79             }
    80         }
    81         for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    82     }
    83     return 0;
    84 }
  • 相关阅读:
    Codeforces 1167E(思路、数据处理)
    Codeforces 185D(发现性质、欧拉定理)
    BUPT2017 springtraining(16) #4 ——基础数论
    Codeforces Round #404 (Div. 2)——ABCDE
    BUPT2017 springtraining(15) #3
    BUPT2017 springtraining(16) #3 ——搜索与动态规划
    BUPT2017 springtraining(16) #2 ——基础数据结构
    Codeforces Round #413(Div. 1 + Div. 2, combined)——ABCD
    BUPT2017 springtraining(16) #1 ——近期codeforces简单题目回顾
    Codeforces Round #400 (Div. 1 + Div. 2, combined)——ABCDE
  • 原文地址:https://www.cnblogs.com/zarth/p/6366182.html
Copyright © 2011-2022 走看看