Ant colony(Codeforces - 474F)

题目来源

https://codeforces.ml/problemset/problem/474/F

题意分析

  题目意思的大致可以描述为,给n个数字,组成一个数组。再给出m次询问,每次询问给出要求的区间的左端点和右端点。求该区间内不能整除所有数字的数的个数。

思路分析

  一般的区间问题,能首先想到的就是几种树、莫队吧。这里最后想到的是线段树。求该区间内不能整除所有数字的数的个数,满足这样条件的数首先是这个区间里面最小的那个数字吧。但是最小的那个数字不一定就是这个区间所有数字的最大公因数。所以我们要记录区间的最大公因数,最小的数字以及最小的数字的个数。当然,只有当最小的那个数是等于该区间内的最大公因数时,要输出的答案里才不包括这些数字,此时我们用区间数字的个数减去最小数字的个数就是最后的答案。而至于一般情况,如果最小的数字和最大公因数两个不同,那么只能说明该区间内没有能够满足该以上条件的数字,那么答案输出的也就是该区间内数字的个数。

  (区间的题目有段时间没写了,确实菜了。。)

code

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <queue>
 4 #include <algorithm>
 5 #include <cstring>
 6 #include <stack>
 7 #include <set>
 8 #include <cmath>
 9 #include <map>
10 
11 #define mod 998244353
12 #define INF 0x3f3f3f3f
13 #define ll long long
14 using namespace std;
15 const double eps = 1e-4;
16 const int maxn = 1e5+7;
17 
18 struct node{
19     int v, num, gc;
20 };
21 
22 node tr[maxn * 4];
23 int a[maxn];
24 
25 int gcd(int a, int b){
26     return b ? gcd(b, a % b) : a;
27 }
28 
29 void build(int l, int r, int x, int &p){
30     if (l == r){
31         tr[x].v = a[p]; tr[x].num = 1; tr[x].gc = a[p ++];
32         return;
33     }
34     int mid = (l + r) >> 1;
35     build(l, mid, x << 1, p);
36     build(mid + 1, r, x << 1 | 1, p);
37     
38     tr[x].gc = gcd(tr[x << 1].gc, tr[x<<1|1].gc);
39     if (tr[x << 1].v < tr[x << 1 | 1].v){
40         tr[x].v = tr[x << 1].v; tr[x].num = tr[x << 1].num;
41     }else if (tr[x << 1].v > tr[x << 1 | 1].v){
42         tr[x].v = tr[x << 1 | 1].v; tr[x].num = tr[x << 1 | 1].num;
43     }else{
44         tr[x].v = tr[x << 1 | 1].v; tr[x].num = tr[x << 1].num + tr[x << 1 | 1].num;
45     }
46 }
47 
48 void query(int L, int R, int l, int r, int x, int &mv, int &mnum, int &mgc){
49     if (L <= l && r <= R){
50         if (mv > tr[x].v){
51             mv = tr[x].v; mnum = tr[x].num;
52         }else if (mv == tr[x].v) mnum += tr[x].num;
53         mgc = gcd(mgc, tr[x].gc);
54         return;
55     }
56     
57     int mid = (l + r) >> 1;
58     if (R > mid) query(L, R, mid + 1, r, x << 1 | 1, mv, mnum, mgc);
59     if (L <= mid) query(L, R, l, mid, x << 1, mv, mnum, mgc);
60 }
61 
62 int main(){
63     int n; scanf("%d", &n);
64     for (int i=1; i<=n; i++) scanf("%d", &a[i]);
65     int t; scanf("%d", &t);
66     int p = 1;
67     build(1, n, 1, p);
68     while (t --){
69         int l, r; scanf("%d%d", &l, &r);
70         int mv = INF, mnum = 0, mgc = 0;
71         query(l, r, 1, n, 1, mv, mnum, mgc);
72         if (mv != mgc) printf("%d\n", r - l + 1);
73         else printf("%d\n", r - l - mnum + 1);
74     }
75     return 0;
76 }
posted @ 2020-07-04 23:06  Rain_island  阅读(208)  评论(0编辑  收藏  举报
Title