您的位置:首页 > 其它

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

2016-07-15 10:51 288 查看
啊回家真是颓,一周了什么都没做

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

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

#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <complex>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <deque>
#include <ctime>

using namespace std;

const double EPS = 1e-8;

#define ABS(x) ((x)<0?(-(x)):(x))
#define SQR(x) ((x)*(x))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))

#define LSON(x) ((x)<<1)
#define RSON(x) (((x)<<1)+1)
#define LOWBIT(x) ((x)&(-(x)))
#define MAXS 1111
#define MAXN 222222
#define VOIDPOINT 0
#define LL long long
#define OO 214748364

struct segTree{
int gcd[MAXN*4], num[MAXN*4], l[MAXN*4], r[MAXN*4], mid[MAXN*4];
int gx, gy, gz;
inline void updata(const int &kok) {
gcd[kok] = __gcd(gcd[LSON(kok)], gcd[RSON(kok)]);
num[kok] = (gcd[kok] == gcd[LSON(kok)] ? num[LSON(kok)] : 0) + (gcd[kok] == gcd[RSON(kok)] ? num[RSON(kok)] : 0);
}
void build(int kok, int ll, int rr, int *a) {
l[kok] = ll; r[kok] = rr;
if (ll == rr) {
gcd[kok] = a[ll]; num[kok] = 1;
return ;
}
int m = mid[kok] = (ll + rr) >> 1;
build(LSON(kok), ll, m, a); build(RSON(kok), m+1, rr, a);
updata(kok);
}
int getGCD(int kok) {
if (gx <= l[kok] && r[kok] <= gy) {
return gcd[kok];
}
if (gy <= mid[kok])
return getGCD(LSON(kok));
else if (gx > mid[kok])
return getGCD(RSON(kok));
else
return __gcd(getGCD(LSON(kok)), getGCD(RSON(kok)));
}
int query(int kok) const {
if (gx <= l[kok] && r[kok] <= gy) {
return gz == gcd[kok] ? num[kok] : 0;
}
if (gy <= mid[kok])
return query(LSON(kok));
else if (gx > mid[kok])
return query(RSON(kok));
else
return (query(LSON(kok)) + query(RSON(kok)));

}
void set(int a = 0, int b = 0, int c = 0) {
gx = a; gy = b; gz = c;
}
} Tree;

int n, a[MAXN];

int main() {
//    freopen("test.txt", "r", stdin);
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", a+i+1);
}
Tree.build(1, 1, n, a);
int m, l, r, t;
scanf("%d", &m);
while (m--) {
scanf("%d%d", &l, &r);
Tree.set(l, r);
t = Tree.getGCD(1);
Tree.set(l, r, t);
printf("%d\n", r - l - Tree.query(1) + 1);
}
return 0;
}


CF474F
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: