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

    Different GCD Subarray Query

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

    分析:

      st表+gcd+二分+树状数组。

      调的心累。

      从一个点为右端点,往左扩展,gcd是单调下降的。而且下降次数不超过log次。于是可以用st表预处理,做到O(1)求区间的gcd。然后二分断点处即可。

      求区间的不同gcd的个数:离线,枚举右端点,考虑计算所有以这个点为右端点的答案,树状数组维护。注意到相同的gcd只会算一次,用last维护上一个出现的位置,这个gcd最右边的位置会替代了左边的所有的位置,只在最右边的gcd的位置加入一个1即可。

      后来在看了几篇博客,发现其实不需要二分!!!直接往左扫过去,如果gcd=1了,就break,而且比二分还快!!!(gcd减少次数本来就不超过log次,可能是数据比较随机的情况下,很快就变成1了。。。)

    代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<cctype>
      7 #include<set>
      8 #include<vector>
      9 #include<queue>
     10 #include<map>
     11 #define fi(s) freopen(s,"r",stdin);
     12 #define fo(s) freopen(s,"w",stdout);
     13 using namespace std;
     14 typedef long long LL;
     15 
     16 inline int read() {
     17     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     18     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     19 }
     20 
     21 const int N = 100005;
     22 
     23 struct Que{
     24     int l, r, id;
     25     bool operator < (const Que &A) const {
     26         return r < A.r;
     27     }
     28 }q[N];
     29 struct Bit{
     30     int n;LL sum[N];
     31     void Clear() { memset(sum, 0, sizeof(sum)); }
     32     void update(int p,int v) {
     33         for (; p<=n; p+=(p&(-p))) sum[p] += v;
     34     }
     35     LL query(int p) {
     36         LL ans = 0;
     37         for (; p; p-=(p&(-p))) ans += sum[p];
     38         return ans;
     39     }
     40 }bit;
     41 int a[N], f[N][20], last[N * 10], Log[N]; // a[i]的范围1e6!!! 
     42 LL ans[N];
     43 int n, Q;
     44 
     45 int gcd(int a,int b) {
     46     return b == 0 ? a : gcd(b, a % b);
     47 }
     48 void init() {
     49     memset(ans, 0, sizeof(ans));
     50     memset(last, 0, sizeof(last));
     51     bit.Clear(); bit.n = n;
     52     for (int i=1; i<=n; ++i) f[i][0] = a[i];
     53     for (int j=1; j<=Log[n]; ++j) 
     54         for (int i=1; (i+(1<<j)-1)<=n; ++i) 
     55             f[i][j] = gcd(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
     56 }
     57 int Gcd(int l,int r) {
     58     int t = Log[r - l + 1];
     59     return gcd(f[l][t], f[r - (1 << t) + 1][t]);
     60 }
     61 int find(int l,int r,int d,int R) { // R! R! R! not r! r! r!
     62     int ans = 0;
     63     while (l <= r) {
     64         int mid = (l + r) >> 1;
     65         if (Gcd(mid, R) == d) ans = mid, r = mid - 1;
     66         else l = mid + 1;
     67     }
     68     return ans - 1;
     69 }
     70 void solve() {
     71     sort(q + 1, q + Q + 1);
     72     int now = 1;
     73     for (int i=1; i<=n; ++i) {
     74         int p = i, d = a[i];
     75         while (p) {
     76             if (!last[d]) bit.update(p, 1);
     77             else if (last[d] < p) bit.update(last[d], -1), bit.update(p, 1);
     78             last[d] = p;
     79             p = find(1, p, d, i);
     80             if (p) d = Gcd(p, i);
     81         }
     82 //        for (int j=i; j; --j,d=Gcd(j,i)) {
     83 //            if (j > last[d]) {
     84 //                if (last[d]) bit.update(last[d], -1);
     85 //                bit.update(j, 1);
     86 //                last[d] = j;
     87 //            }
     88 //            if (d == 1) break;
     89 //        }
     90         while (now <= Q && q[now].r == i) {
     91             ans[q[now].id] = bit.query(q[now].r) - bit.query(q[now].l - 1);
     92             now ++;
     93         }
     94     }
     95     for (int i=1; i<=Q; ++i) printf("%lld
    ",ans[i]);
     96 }
     97 int main() { 
     98     Log[0] = -1;
     99     for (int i=1; i<=100000; ++i) Log[i] = Log[i >> 1] + 1;
    100     while (~scanf("%d%d", &n, &Q)) {
    101         for (int i=1; i<=n; ++i) a[i] = read();
    102         init();
    103         for (int i=1; i<=Q; ++i) 
    104             q[i].l = read(), q[i].r = read(), q[i].id = i;
    105         solve();
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    个人冲刺二(2)
    个人冲刺二(1)
    三个和尚观后感
    每日总结
    个人冲刺(10)
    个人冲刺(9)
    个人冲刺(8)
    个人冲刺(7)
    个人冲刺(6)
    下次视频面试前把电脑摄像头擦干净吧
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9758737.html
Copyright © 2011-2022 走看看