CF 474/F, 线段树 + 一点数学

啊回家真是颓,一周了什么都没做

题目大意:给出一坨数,每次询问区间当中有多少个数能把其他区间内的所有数整除

解:由于我是知道这个是线段树专题,所以一开始就奔着gcd去了,想了一下还真是gcd,因为如果一个数a能整除另一个数b,那么gcd(a,b)一定为a,所以这说明可以做区间加法,直接上线段树就是,询问个数的时候还傻叉地想了一会,后面发现给每个线段记一下当前线段表示的gcd有几个就行,合并直接合并(可以证明现在这个线段的gcd一定是作为最优的取值,因为没有数等于这个gcd说明没有数能整除当前区间,那么合并上去也不会导致少解)

 

 1 #include <cstdio>
 2 #include <string>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <cstring>
 7 #include <complex>
 8 #include <set>
 9 #include <vector>
10 #include <map>
11 #include <queue>
12 #include <deque>
13 #include <ctime>
14 
15 using namespace std;
16 
17 const double EPS = 1e-8;
18 
19 #define ABS(x) ((x)<0?(-(x)):(x))
20 #define SQR(x) ((x)*(x))
21 #define MIN(a,b) ((a)<(b)?(a):(b))
22 #define MAX(a,b) ((a)>(b)?(a):(b))
23 
24 #define LSON(x) ((x)<<1)
25 #define RSON(x) (((x)<<1)+1)
26 #define LOWBIT(x) ((x)&(-(x)))
27 #define MAXS 1111
28 #define MAXN 222222
29 #define VOIDPOINT 0
30 #define LL long long
31 #define OO 214748364
32 
33 
34 struct segTree{
35     int gcd[MAXN*4], num[MAXN*4], l[MAXN*4], r[MAXN*4], mid[MAXN*4];
36     int gx, gy, gz;
37     inline void updata(const int &kok) {
38         gcd[kok] = __gcd(gcd[LSON(kok)], gcd[RSON(kok)]);
39         num[kok] = (gcd[kok] == gcd[LSON(kok)] ? num[LSON(kok)] : 0) + (gcd[kok] == gcd[RSON(kok)] ? num[RSON(kok)] : 0);        
40     }
41     void build(int kok, int ll, int rr, int *a) {
42         l[kok] = ll; r[kok] = rr;
43         if (ll == rr) {
44             gcd[kok] = a[ll]; num[kok] = 1;
45             return ;
46         }
47         int m = mid[kok] = (ll + rr) >> 1;
48         build(LSON(kok), ll, m, a); build(RSON(kok), m+1, rr, a);
49         updata(kok);
50     }
51     int getGCD(int kok) {
52         if (gx <= l[kok] && r[kok] <= gy) {
53             return gcd[kok];
54         }
55         if (gy <= mid[kok]) 
56             return getGCD(LSON(kok));
57         else if (gx > mid[kok]) 
58             return getGCD(RSON(kok));
59         else
60             return __gcd(getGCD(LSON(kok)), getGCD(RSON(kok)));
61     }
62     int query(int kok) const {
63         if (gx <= l[kok] && r[kok] <= gy) {
64             return gz == gcd[kok] ? num[kok] : 0;
65         }
66         if (gy <= mid[kok]) 
67             return query(LSON(kok));
68         else if (gx > mid[kok]) 
69             return query(RSON(kok));
70         else
71             return (query(LSON(kok)) + query(RSON(kok)));
72 
73     }
74     void set(int a = 0, int b = 0, int c = 0) {
75         gx = a; gy = b; gz = c;
76     }
77 } Tree;
78 
79 int n, a[MAXN];
80 
81 int main() {
82 //    freopen("test.txt", "r", stdin);
83     scanf("%d", &n);
84     for (int i = 0; i < n; ++i) {
85         scanf("%d", a+i+1);
86     }
87     Tree.build(1, 1, n, a);
88     int m, l, r, t;
89     scanf("%d", &m);
90     while (m--) {
91         scanf("%d%d", &l, &r);
92         Tree.set(l, r);
93         t = Tree.getGCD(1);
94         Tree.set(l, r, t);
95         printf("%d\n", r - l - Tree.query(1) + 1);
96     }
97     return 0;
98 }
CF474F

 

posted @ 2016-07-15 10:51  F.D.His.D  阅读(334)  评论(0编辑  收藏  举报