hdu4777 hdu 4777 Rabbit Kingdom 因子分解 + 离线树状数组

【题意】

给定N个数,M个查询,每个查询[L,R]内 与所有数互质的数的个数。所有数都小于200000.

【分析】

预处理第i个数,和他互质的数的区间[li,ri].因子分解从前往后和从后往前扫一遍即可求出。

然后问题就是求区间[L,R]被多少个[li,ri]{L<=i<=R}完全覆盖的问题了。

转化问题为求没有完全覆盖[L,R]的区间有多少个,做减法即可。

考虑区间相交的几种情况,判断哪些位置没有完全覆盖。用树状数组维护即可。

离线处理,把询问按照R排序。 

未完待续。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <math.h>
  4 #include <vector>
  5 #include <algorithm>
  6 
  7 using namespace std;
  8 
  9 const int maxn = 200010;
 10 int n, m;
 11 
 12 struct BIT
 13 {
 14     int dt[maxn];
 15     void init()
 16     {
 17         memset(dt,0,sizeof dt);
 18     }
 19     int lowbit(int x)
 20     {
 21         return x&(-x);
 22     }
 23 
 24     void modify(int pos,int c)
 25     {
 26         if (pos<=0 || pos>n) return;
 27 
 28         for (int x=pos; x<maxn; x+=lowbit(x))
 29         dt[x]+=c;
 30     }
 31     int query(int pos)
 32     {
 33         int res=0;
 34         for (int x=pos; x>0; x-=lowbit(x))
 35         res+=dt[x];
 36         return res;
 37     }
 38 }bit;
 39 
 40 
 41 
 42 struct query{
 43     int L,R;
 44     int id;
 45 
 46     bool operator < (const query &q)const{
 47         return R < q.R;
 48     }
 49 }que[maxn];
 50 bool cmp(query p, query q)
 51 {
 52     return p.R < q.R;
 53 }
 54 
 55 vector<int> fac[maxn];
 56 vector<int> sq[maxn];
 57 int a[maxn];
 58 int l[maxn];
 59 int r[maxn];
 60 int last[maxn];
 61 int ans[maxn];
 62 
 63 int main()
 64 {
 65     for (int i=1;i<maxn;i++){
 66         fac[i].clear();
 67     }
 68     for (int i=2;i<maxn;i++){
 69         for (int j=i;j<maxn;j+=i){
 70             fac[j].push_back(i);
 71         }
 72     }
 73     int cas;
 74     while (scanf("%d%d", &n, &m))
 75     {
 76 
 77         for (int i=1;i<=n;i++){
 78             sq[i].clear();
 79         }
 80 
 81         if (n==0 && m==0)
 82             break;
 83         for (int i=1;i<=n;i++){
 84             scanf("%d", &a[i]);
 85         }
 86         memset(last, 0, sizeof(last));
 87         for (int i=1;i<=n;i++){
 88             int maxp = 0;
 89             for (int j = 0;j<fac[a[i]].size();j++){
 90                 maxp = max(maxp, last[fac[a[i]][j]]);
 91                 last[fac[a[i]][j]] = i;
 92             }
 93             l[i] = maxp + 1;
 94            // printf("l = %d %d\n",i,l[i]);
 95         }
 96         memset(last, 0x3f3f3f, sizeof(last));
 97         for (int i=n;i>=1;i--){
 98             int minp = 0x3f3f3f;
 99             for (int j=0;j<fac[a[i]].size();j++){
100                 minp = min(minp, last[fac[a[i]][j]]);
101                 last[fac[a[i]][j]] = i;
102             }
103             minp =  min(n+1, minp);
104             r[i] = minp - 1;
105             //printf("r = %d %d\n",i,r[i]);
106         }
107         for (int i=0;i<m;i++)
108         {
109             scanf("%d%d", &que[i].L, &que[i].R);
110             que[i].id = i;
111         }
112         sort(que, que+m);
113 
114         int pos = 0;
115         bit.init();
116 
117         for (int i=1;i<=n && pos<m;i++){
118             for (int j=0; j < sq[i].size();j++){
119                 bit.modify(sq[i][j], 1);
120                 bit.modify(l[sq[i][j]]-1, -1);
121             }
122             bit.modify(l[i]-1, 1);
123             while (que[pos].R == i && pos < m)
124             {
125                 int tmp = bit.query(que[pos].R) - bit.query(que[pos].L - 1);
126 
127                 ans[que[pos].id] = que[pos].R - que[pos].L + 1 - tmp;
128                 pos++;
129             }
130             int tmp = r[i] + 1;
131             if (tmp <= n){
132                 sq[tmp].push_back(i);
133             }
134         }
135         for (int i=0;i<m;i++)
136         {
137             printf("%d\n",ans[i]);
138         }
139     }
140     return 0;
141 }
hdu4777

 

 

转载于:https://www.cnblogs.com/wangsouc/articles/3637946.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值