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 }