HDU 4777 Rabbit Kingdom

Rabbit Kingdom

Time Limit: 3000ms
Memory Limit: 32768KB
This problem will be judged on  HDU. Original ID: 4777
64-bit integer IO format: %I64d      Java class name: Main
  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 Wi 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, Wi <= 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] .
 

Source

 
解题:首先我们需要处理各数距离它左边最近和右边最近的与其不互质的数
  1. $nxt[p]记录最新的含有p因子的数的位置$
  2. $然后分解当前数的因子,就可以找出上个含有p因子的数的位置$
  3. $然后就可以更新上个数的最近的右边不互质数的位置已经当前数左边最近的不互质数的位置$
接下来就是利用树状数组更新
  1. 对所有左边界为i的数,我们可以把他们对应的位置上加1
  2. 然后对应位置的右边界减去1,因为如果超过右边界,那么对应位置这个数就不应该算进去,所以要减1
  3. 用MS C++交,G++爆内存,奶奶的
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 #include <algorithm>
 6 using namespace std;
 7 const int maxn = 200010;
 8 struct QU {
 9     int L,R,id;
10     bool operator<(const QU &rhs)const {
11         return L < rhs.L;
12     }
13 } Q[maxn];
14 int C[maxn],L[maxn],R[maxn],nxt[maxn],d[maxn],ans[maxn],n,m;
15 vector<int>fac[maxn];
16 vector<int>Ls[maxn];
17 void init() {
18     for(int i = 2; i <= 200000; ++i)
19         for(int j = i; j <= 200000; j += i)
20             fac[j].push_back(i);
21 }
22 int sum(int i,int ret = 0) {
23     while(i > 0) {
24         ret += C[i];
25         i -= i&-i;
26     }
27     return ret;
28 }
29 void add(int i,int val) {
30     while(i <= n) {
31         C[i] += val;
32         i += i&-i;
33     }
34 }
35 void solve() {
36     for(int i = 0; i <= n; ++i) Ls[i].clear();
37     sort(Q,Q + m);
38     memset(C,0,sizeof C);
39     memset(L,0,sizeof L);
40     memset(R,0,sizeof R);
41     memset(nxt,0,sizeof nxt);
42     for(int i = 1; i <= n; ++i) {
43         for(int j = 0; j < fac[d[i]].size(); ++j) {
44             int p = fac[d[i]][j];
45             if(!nxt[p]){
46                 nxt[p] = i;
47                 continue;
48             }
49             if(!R[nxt[p]]) R[nxt[p]] = i;
50             if(L[i] < nxt[p]) L[i] = nxt[p];
51             nxt[p] = i;
52         }
53         Ls[L[i]].push_back(i);
54     }
55     for(int i = 0,cur = 0; i <= n; ++i){
56         while(Q[cur].L == i){
57             ans[Q[cur].id] = sum(Q[cur].R) - sum(Q[cur].L - 1);
58             ++cur;
59         }
60         for(int j = 0; j < Ls[i].size(); ++j){
61             add(Ls[i][j],1);
62             if(R[Ls[i][j]]) add(R[Ls[i][j]],-1);
63         }
64         if(R[i]) add(R[i],1);
65     }
66     for(int i = 0; i < m; ++i)
67         printf("%d\n",ans[i]);
68 }
69 int main() {
70     init();
71     while(scanf("%d%d",&n,&m),n||m) {
72         for(int i = 1; i <= n; ++i) scanf("%d", d + i);
73         for(int i = 0; i < m; ++i) {
74             scanf("%d%d",&Q[i].L,&Q[i].R);
75             Q[i].id = i;
76         }
77         solve();
78     }
79     return 0;
80 }
View Code

 

 
 

转载于:https://www.cnblogs.com/crackpotisback/p/4848654.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值