• (树状数组)HDU


     Long long ago, there was an ancient rabbit kingdom in the forest. Every rabbit in this kingdom was not cute but totally pugnacious, so the kingdom was in chaos in season and out of season.
      n rabbits were numbered form 1 to n. All rabbits' weight is an integer. For some unknown reason, two rabbits would fight each other if and only if their weight is NOT co-prime.
      Now the king had arranged the n rabbits in a line ordered by their numbers. The king planned to send some rabbits into prison. He wanted to know that, if he sent all rabbits between the i-th one and the j-th one(including the i-th one and the j-th one) into prison, how many rabbits in the prison would not fight with others.
      Please note that a rabbit would not fight with himself.

    Input  The input consists of several test cases.
      The first line of each test case contains two integer n, m, indicating the number of rabbits and the queries.
      The following line contains n integers, and the i-th integer W i indicates the weight of the i-th rabbit.
      Then m lines follow. Each line represents a query. It contains two integers L and R, meaning the king wanted to ask about the situation that if he sent all rabbits from the L-th one to the R-th one into prison.
      (1 <= n, m, W i <= 200000, 1 <= L <= R <= n)
      The input ends with n = 0 and m = 0.
    Output  For every query, output one line indicating the answer.Sample Input

    3 2
    2 1 4
    1 2
    1 3
    6 4
    3 6 1 2 5 3
    1 3
    4 6
    4 4
    2 6
    0 0

    Sample Output

    2
    1
    1
    3
    1
    2
    
            
     

    Hint

      In the second case, the answer of the 4-th query is 2, because only 1 and 5 is co-prime with other numbers in the interval [2,6] .
    

    题意:

    给n个数,m次询问,每次询问一个区间,求该区间内有多少数与该区间其它数均互质。

    首先,对于每一个数,都必存在一个最大的l和一个最小的r,满足下标在[l,r]区间内时与区间内所有其他数均互质。对于每次查询的区间,当且仅当[l,r]包含这个区间时,这个数才有贡献。

    故我们可以考虑先预处理每个数的l和r,之后离线处理所有查询。先对所有查询按l从小到大,r从小到大的顺序排序,这样处理时就可以极大节省时间复杂度。

    每次新查询的一个区间,就只需维护当前有多少符合条件的[l,r]区间。这只需要在上一次的基础上添加(add 1)和删除(add -1)即可。

      1 #include <iostream>
      2 #include <string>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <queue>
      8 #include <set>
      9 #include <map>
     10 #include <list>
     11 #include <vector>
     12 #include <stack>
     13 #define mp make_pair
     14 //#define P make_pair
     15 #define MIN(a,b) (a>b?b:a)
     16 //#define MAX(a,b) (a>b?a:b)
     17 #define REP(I,N) for (I=0;I<N;I++)
     18 #define rREP(I,N) for (I=N-1;I>=0;I--)
     19 #define rep(I,S,N) for (I=S;I<N;I++)
     20 #define rrep(I,S,N) for (I=N-1;I>=S;I--)
     21 #define FOR(I,S,N) for (I=S;I<=N;I++)
     22 #define rFOR(I,S,N) for (I=N;I>=S;I--)
     23 typedef long long ll;
     24 typedef unsigned long long ull;
     25 const int MAX=2e5+5;
     26 const int INF=1e7+5;
     27 using namespace std;
     28 //const int MOD=1e9+7;
     29 typedef pair<ll,int> pii;
     30 const double eps=0.00000001;
     31 const int limit=2e5;
     32 int n,m;
     33 int c[MAX];
     34 inline int lowbit(int x)
     35 {
     36     return x&-x;
     37 }
     38 int presum(int x)//前缀和
     39 {
     40     int re=0;
     41     while(x)
     42     {
     43         re+=c[x];
     44         x-=lowbit(x);
     45     }
     46     return re;
     47 }
     48 int sum(int l,int r)
     49 {
     50     return presum(r)-presum(l-1);
     51 }
     52 void add(int x,int d)
     53 {
     54     while(x<=n+1)
     55     {
     56         c[x]+=d;
     57         x+=lowbit(x);
     58     }
     59 }
     60 void init(int n)
     61 {
     62     int i;
     63     FOR(i,1,n+1) c[i]=0;
     64 }
     65 struct node
     66 {
     67     int l,r,i;
     68 }Q[MAX];
     69 int ans[MAX];
     70 bool cmp(node a,node b)
     71 {
     72     if(a.l!=b.l)
     73         return a.l<b.l;
     74     else
     75         return a.r<b.r;
     76 }
     77 int prepos[MAX];
     78 int l[MAX],r[MAX];
     79 int a[MAX],b[MAX];
     80 vector<int>L[MAX];
     81 void solve()
     82 {
     83     int i,j,k;
     84     FOR(i,1,n) scanf("%d",&a[i]),b[i]=a[i];
     85     memset(prepos,0,sizeof(prepos));
     86     FOR(i,1,n)
     87     {
     88         l[i]=1;
     89         for(k=2;k*k<=a[i];k++)
     90         {
     91             if(a[i]%k==0)
     92             {
     93                 l[i]=max(l[i],prepos[k]+1);
     94                 while(a[i]%k==0)
     95                     a[i]/=k;
     96                 prepos[k]=i;
     97             }
     98         }
     99         if(a[i]>1)
    100         {
    101             k=a[i];
    102             l[i]=max(l[i],prepos[k]+1);
    103             prepos[k]=i;
    104         }
    105     }
    106     FOR(i,1,limit) prepos[i]=n+1;
    107     rFOR(i,1,n)
    108     {
    109         r[i]=n;
    110         for(k=2;k*k<=b[i];k++)
    111         {
    112             if(b[i]%k==0)
    113             {
    114                 r[i]=min(r[i],prepos[k]-1);
    115                 while(b[i]%k==0)
    116                     b[i]/=k;
    117                 prepos[k]=i;
    118             }
    119         }
    120         if(b[i]>1)
    121         {
    122             k=b[i];
    123             r[i]=min(r[i],prepos[k]-1);
    124             prepos[k]=i;
    125         }
    126     }
    127     FOR(i,1,n) vector<int>().swap(L[i]);
    128     FOR(i,1,n) L[l[i]].push_back(i);
    129     REP(i,m) scanf("%d%d",&Q[i].l,&Q[i].r),Q[i].i=i;
    130     init(n);
    131     sort(Q,Q+m,cmp);
    132     int now1=0;
    133     REP(i,m)
    134     {
    135         while(now1<Q[i].l)
    136         {
    137             if(now1)
    138                 add(now1,-1),add(r[now1]+1,1);
    139             now1++;
    140             for(int k:L[now1])
    141             {
    142                 add(k,1);
    143                 add(r[k]+1,-1);
    144             }
    145         }
    146         ans[Q[i].i]=sum(Q[i].l,Q[i].r);
    147     }
    148     REP(i,m) printf("%d
    ",ans[i]);
    149 }
    150 int main()
    151 {
    152     while(scanf("%d%d",&n,&m)&&(n||m))
    153         solve();
    154 }
  • 相关阅读:
    Golang Gin 实战(一)| 快速安装入门
    6 款最棒的 Go 语言 Web 框架简介
    Golang教科书般的web框架
    vgo简明教程
    go mod常用命令 已经 常见问题
    线程池原理讲解 Java专题
    Python 3.9安装与使用
    消息队列的基本概念
    实践——GIT安装(2021/05/01)
    vue2.0数据双向绑定原理分析及代码实现
  • 原文地址:https://www.cnblogs.com/quintessence/p/7247596.html
Copyright © 2020-2023  润新知