CCF 201709-5 除法(线段树)
Posted qaqorz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF 201709-5 除法(线段树)相关的知识,希望对你有一定的参考价值。
操作1:给[l, r]中v的倍数除v
操作2:查询[l, r]的和
思路:类似势能线段树(例题:HDU4027)的思想,首先忽略v=1的操作,然后,1e6数据范围内的数就算每次都除以2,也不用太多次就能变为1,而变为1之后就不用再处理了,所以遍历区间[l, r]找到需要修改的数进行单点修改就行了
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define LL long long 6 #define debug(x) cout << "[" << x << "]" << endl 7 #define lid id << 1 8 #define rid id << 1 | 1 9 using namespace std; 10 11 const int mx = 1e5+5; 12 struct tree{ 13 int l, r; 14 LL sum; 15 }tree[mx<<2]; 16 int a[mx]; 17 18 void push_up(int id){ 19 tree[id].sum = tree[lid].sum + tree[rid].sum; 20 } 21 22 void build(int l, int r, int id){ 23 tree[id].l = l; 24 tree[id].r = r; 25 if (l == r){ 26 tree[id].sum = a[l]; 27 return; 28 } 29 int mid = (l+r)>>1; 30 build(l, mid, lid); 31 build(mid+1, r, rid); 32 push_up(id); 33 } 34 35 void upd(int x, int id, int c){ 36 if (tree[id].l == tree[id].r){ 37 tree[id].sum = c; 38 return; 39 } 40 int mid = (tree[id].l + tree[id].r)>>1; 41 if (x <= mid) upd(x, lid, c); 42 else upd(x, rid, c); 43 push_up(id); 44 } 45 46 LL query(int l, int r, int id){ 47 if (tree[id].l == l && tree[id].r == r) return tree[id].sum; 48 int mid = (tree[id].l + tree[id].r) >> 1; 49 if (mid >= r) return query(l, r, lid); 50 else if (mid < l) return query(l, r, rid); 51 return query(l, mid, lid) + query(mid+1, r, rid); 52 } 53 54 int main(){ 55 int n, q; 56 scanf("%d%d", &n, &q); 57 for (int i = 1; i <= n; i++) scanf("%d", &a[i]); 58 build(1, n, 1); 59 while (q--){ 60 int op, l, r, c; 61 scanf("%d%d%d", &op, &l, &r); 62 if (op == 1){ 63 scanf("%d", &c); 64 if (c == 1) continue; 65 for (int i = l; i <= r; i++){ 66 if (a[i] >= c && a[i]%c == 0){ 67 a[i] /= c; 68 upd(i, 1, a[i]); 69 } 70 } 71 } 72 else printf("%lld ", query(l, r, 1)); 73 } 74 return 0; 75 }
以上是关于CCF 201709-5 除法(线段树)的主要内容,如果未能解决你的问题,请参考以下文章