Codeforces 920F. SUM and REPLACE

题目大意:

一个数列 支持两种操作

1 把区间内的数变成他们自己的约数个数

2 求区间和

思路:

可以想到每个数最终都会变成2或1

然后我们可以线段树

修改的时候记录一下每段有没有全被修改成1或2 是的话就不修改了

不是就暴力修改 因为每个数被修改的次数很小

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 1001000
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();}
18     return x*f;
19 }
20 int n,g[MAXN],cnt[MAXN],m;
21 struct data{ll sum,mx;}tr[MAXN<<2];
22 inline void pshp(int k)
23 {
24     tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
25     tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);
26 }
27 void build(int k,int l,int r)
28 {
29     if(l==r) {tr[k].sum=tr[k].mx=g[l];return ;}
30     int mid=(l+r)>>1;
31     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
32     pshp(k);
33 }
34 inline ll query(int k,int a,int b,int l,int r)
35 {
36     if(l==a&&r==b) return tr[k].sum;
37     int mid=(l+r)>>1;
38     if(mid>=b) return query(k<<1,a,b,l,mid);
39     else if(mid<a) return query(k<<1|1,a,b,mid+1,r);
40     else return query(k<<1,a,mid,l,mid)+query(k<<1|1,mid+1,b,mid+1,r);
41 }
42 inline void upd(int k,int a,int b,int l,int r)
43 {
44     if(tr[k].mx<=2) return ;
45     if(l==r) {tr[k].sum=tr[k].mx=cnt[tr[k].mx];return ;}
46     int mid=(l+r)>>1;
47     if(mid>=b) upd(k<<1,a,b,l,mid);
48     else if(mid<a) upd(k<<1|1,a,b,mid+1,r);
49     else {upd(k<<1,a,mid,l,mid);upd(k<<1|1,mid+1,b,mid+1,r);}
50     pshp(k);
51 }
52 int main()
53 {
54     int a,b,c;
55     for(int i=1;i<=MAXN;i++)
56         for(int j=i;j<=MAXN;j+=i) cnt[j]++;
57     n=read(),m=read();
58     for(int i=1;i<=n;i++) g[i]=read();
59     build(1,1,n);
60     while(m--)
61     {
62         a=read(),b=read(),c=read();
63         if(a==1) upd(1,b,c,1,n);
64         else printf("%I64d\n",query(1,b,c,1,n));
65     }
66 }

原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8448508.html

时间: 2024-07-31 05:35:02

Codeforces 920F. SUM and REPLACE的相关文章

CodeForces - 920F SUM and REPLACE (线段树)

题意:给N个数M次操作,(1<=N,M<=3e5, 1<=ai<=1e6),1是使[L,R]中的每个元素变成其因子的个数之和:2是求[L,R]区间之和 分析:看上去就很线段树的一题,但是却思考了很久.发现1和2即使对其,也不会改变二者的值.而且一个大于2的数进行多次1操作,也最终会退化到2. 先预处理筛出1e6以内各数的质因子个数和.在线段树的节点中维护两个值:区间和以及区间最大值.在update函数中,如果该区间的最大值不超过2,那么该区间没有更新的必要:若超过2,则递归向下找到

Codefroces 920F SUM and REPLACE(线段树)

SUM and REPLACE 题意:给你n个数,进行m次操作,分别是将区间[l,r]内的所有数替换成自己的因子数 和 对区间[l,r]进行求和. 题解:可以发现2的因子个数还是2,1的因子个数还是1,所以如果某个数被更新成1或者2之后就不需要再进行更新了. 1 #include<bits/stdc++.h> 2 #define ll long long 3 #define lson l,m,rt<<1 4 #define rson m+1,r,rt<<1|1 5 us

codeforces CF920F SUM and REPLACE 线段树 线性筛约数

$ \Rightarrow $ 戳我进CF原题 F. SUM and REPLACE time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard input output: standard output Let $ D(x) $ be the number of positive divisors of a positive integer $ x $ . For example, $

Educational Codeforces Round 37-F.SUM and REPLACE (线段树,线性筛,收敛函数)

F. SUM and REPLACE time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard output Let D(x) be the number of positive divisors of a positive integer x. For example, D(2)?=?2 (2 is divisible by 1 and 2), D(6)?

codeforces 85D. Sum of Medians

二次联通门 : codeforces 85D. Sum of Medians /* codeforces 85D. Sum of Medians 正解线段树或是平衡树 结果用vector暴力卡过去了 */ #include <algorithm> #include <iostream> #include <cstdio> #include <vector> using namespace std; void read (int &now) { reg

CF920F SUM and REPLACE 题解

CF920F SUM and REPLACE 线段树例题解析合集 和模板的不同之处在于修改时是改为每个数的约数个数,不难发现,当一个数x<=2时,x的约数个数与本身相等,修改多少次多不会在改变 先预处理出每个数的约数个数,用线段树维护区间最大值,若<=2,则直接结束递归 对于>2的数都要暴力修改,但由于每个数的约数个数下降很快,几次后便降到<=2,所以复杂度优秀(大约是nlogn?) 这题与CF438D The Child and Sequence(区间取模),类似,也可以维护区间

【Educational Codeforces Round 37】F. SUM and REPLACE 线段树+线性筛

题意 给定序列$a_n$,每次将$[L,R]$区间内的数$a_i$替换为$d(a_i)$,或者询问区间和 这题和区间开方有相同的操作 对于$a_i \in (1,10^6)$,$10$次$d(a_i)$以内肯定可以最终化为$1$或者$2$,所以线段树记录区间最大值和区间和,$Max\le2$就返回,单点暴力更新,最后线性筛预处理出$d$ 时间复杂度$O(m\log n)$ 代码 #include <bits/stdc++.h> using namespace std; typedef long

Codeforces 85D Sum of Medians(线段树)

85D Sum of Medians 题目链接 题意:一个集合有添加,删除元素,每次查询输出集合位置为i % 5 == 3的位置和 思路:线段树,线段树记录下% 5 == 0, 1, 2, 3, 4的和,并且记录一个mov表示右移多少,每次添加一个值的时候,就当前位置之后的一整段位置都要右移一个单位,这样去搞线段树维护一下即可 代码: #include <cstdio> #include <cstring> #include <cstdlib> #include <

[Codeforces 1242C]Sum Balance

Description 题库链接 给你 \(k\) 个盒子,第 \(i\) 个盒子中有 \(n_i\) 个数,第 \(j\) 个数为 \(x_{i,j}\).现在让你进行 \(k\) 次操作,第 \(i\) 次操作要求从第 \(i\) 个盒子中取出一个元素(这个元素最开始就在该盒子中),放入任意一个你指定的盒子中,要求经过 \(k\) 次操作后 所有盒子元素个数和最开始相同: 所有盒子元素总和相等 询问是否存在一种操作方式使之满足,若存在,输出任意一种方案即可. \(1\leq k\leq 15