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

时间: 2024-11-10 13:27:10

CF 474/F, 线段树 + 一点数学的相关文章

cf 121 E 线段树解法

题意:给n个数 m次操作 操作方式为 count 统计区间里的幸运数字都多少个 add给区间里每个数都加上一个值 网上的大牛都是用树状数组写的 线段树也可以解决 只是有点悬  刚学线段树 借此加强知识储备和代码能力 线段树单点更新 谢谢各位指教 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using name

bzoj4821 &amp;&amp; luogu3707 SDOI2017相关分析(线段树,数学)

题目大意 给定n个元素的数列,每一个元素有x和y两种元素,现在有三种操作: \(1\ L\ R\) 设\(xx\)为\([l,r]\)的元素的\(x_i\)的平均值,\(yy\)同理 求 \(\frac{\sum_{i=L}^R(x_i-xx)(y_i-yy)} {\sum_{i=L}^R(xi-xx)^2}\) \(2\ L\ R\ S\ T\\) 将\([L,R]\)中的每个元素的\(x_i\)+S,\(y_i\)+T $3 L R S T  $ 对于\([L,R]\)中的每个元素,设其为\

F - Problem F( 线段树 )

度熊手上有一本字典存储了大量的单词,有一次,他把所有单词组成了一个很长很长的字符串.现在麻烦来了,他忘记了原来的字符串都是什么,神奇的是他竟然记得原来那些字符串的哈希值.一个字符串的哈希值,由以下公式计算得到: H(s)=∏i≤len(s)i=1(Si?28) (mod 9973)SiSi代表 S[i] 字符的 ASCII 码. 请帮助度熊计算大字符串中任意一段的哈希值是多少. Input多组测试数据,每组测试数据第一行是一个正整数NN,代表询问的次数,第二行一个字符串,代表题目中的大字符串,接

河南省多校联盟二-F 线段树+矩阵

---恢复内容开始--- 1284: SP教数学 时间限制: 2 秒  内存限制: 128 MB提交: 24  解决: 4 题目描述 输入 输出 对于每组数据的2操作,输出一行对1e9 + 7取模的答案 样例输入 7 4 2 2 1 1 3 3 2 2 1 5 2 6 7 1 3 4 3 2 6 6 样例输出 6 3 2 提示 1 <=  n ,m <=10^5 一道很有趣的ST的题目,有趣在维护节点时用到了矩阵运算,减少了计算量. 首先对于矩阵运算法则,百度百科: 基本性质 乘法结合律: (

HAOI2012高速公路bzoj2752 (线段树,数学)

题目大意: 给定一个长度为n的链,一共m次操作 对于每次操作 \(C\ l\ r\ x\)表示将第l个点到第r个点之间的所有道路的权值增加v \(Q\ l\ r\)在第l个到第r个点里等概率随机取出两个不同的点a和b,那么从a行驶到b将期望花费多少费用呢 QwQ我们可以考虑将期望分为分子和分母两部分 首先考虑分母,分母就是在\(r-l+1\)个点中选两个点的方案数,也就是\({r-l+1}\choose 2\) 而分子就是总权值了 对于一个在\([l,r]\)的点\(i\)来说 它会被计算\((

codeforces 765 F 线段树+set

题意:多次询问区间内 两数差的绝对值的最小值 题解:离线询问则可以按照询问的l排序,倒着询问,倒着从r更新到l 每次更新i+1到n这个区间,保证这次的更新不会影响到下一次以及以后的更新.因为当两个区间出现覆盖时,l更小的那个区间的值一定小于等于另一个,画个图就可以明白. #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <map>

POJ 3667 线段树区间合并

http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html 用线段树,首先要定义好线段树的节点信息,一般看到一个问题,很难很快能确定线段树要记录的信息做线段树不能为了做题而做,首先线段树是一种辅助结构,它是为问题而生的,因而必须具体问题具体分析回忆一下RMQ问题,其实解决RMQ有很多方法,根本不需要用到线段树,用线段树解决RMQ,其实是利用线段树的性质来辅助解决这个问题回忆一下求矩形面积并或周长并的问题,一般使用的是扫描

poj 3667 Hotel (线段树的合并操作)

Hotel The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the competent travel agent, has named the Bullmoose Hotel on famed Cumberland Street as t

【线段树】【树状数组】【CF 121E】幸运数列

1922. [CF 121E]幸运数列 ★★★ 输入文件:cf121e.in 输出文件:cf121e.out 简单对比 时间限制:3 s 内存限制:256 MB [题目描述] 对于欧洲人来说,"幸运数"是指那些十进制只由4或7组成的数.财务员Petya需要维护一个支持如下操作的整数数列: add l r d - 表示将[l, r]区间内的所有数加上一个正整数d(). count l r - 统计[l, r]区间内有多少个"幸运数".() 请你帮助Petya实现它.