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 }
  • 相关阅读:
    js的继承实现方式
    jdbc调用通用存储过程完成分页
    最近在忙些什么......
    【转】说服下属的“攻心术”
    设计模式原则详解
    【转】职场学做“功夫熊猫”
    内核初始化优化宏 ,初始化顺序, __init,__devexit等
    Linux 嵌入式启动以及优化
    每个程序员都该知道的10大编程格言
    linux 用户空间 和 内核空间 延时函数
  • 原文地址:https://www.cnblogs.com/zarth/p/6366182.html
Copyright © 2011-2022 走看看