Codeforces 920F

<题目链接>

题目大意:

给你一个序列,有两个操作,一个是求区间 l - r 的和,另一个是对区间l-r的元素修改值,x=d(x),d(x)为x的因子个数。

解题分析:

因为可能有多次修改操作,并且修改的范围可能比较大,所以提前将1~1e6范围内的数的因子个数全部打表进行处理。但是仅仅这样还是不行的,因为如果每次区间更新都暴力更新到叶子节点的话,区间更新 $O(nlog(n))$ ,然后m次询问,时间复杂度就达到了$O(n*mlog(n))$,而本题n给到了3e5,毫无疑问这样暴力更新是会超时的。我们发现1、2的因子数为它们本身,所以在更新的过程中,如果该区间都为1或2,就不用继续向下进行更新。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N int(3e5+7)
 5 #define Max int(1e6+7)
 6 #define lson rt<<1,l,mid
 7 #define rson rt<<1|1,mid+1,r
 8 #define clr(a,b) memset(a,b,sizeof(a))
 9 #define rep(i,s,t) for(int i=s;i<=t;i++)
10 typedef long long ll;
11 int n,q;
12 int arr[N],facnum[Max+100];
13 ll flag[N<<2],tr[N<<2];
14 
15 template<typename T>
16 inline T read(T&x){
17     x=0;int f=0;char ch=getchar();
18     while(ch<'0'||ch>'9')f|=(ch=='-'),ch=getchar();
19     while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();
20     return x=f?-x:x;
21 }
22 int Getfac(int x){     //得到该数的所有因子数
23     int sum=1,cnt;
24     for(int i=2;i*i<=x;i++){
25         cnt=0;
26         while(x%i==0)x/=i,cnt++;
27         sum*=(cnt+1);
28     }
29     if(x>1) sum*=2;
30     return sum;
31 }
32 void Pushup(int rt){
33     tr[rt]=tr[rt<<1]+tr[rt<<1|1];
34     if(!flag[rt<<1]&&!flag[rt<<1|1])flag[rt]=0;     //如果两个子区间都不需要修改,说明这个区间不需要再进行修改
35 }
36 void build(int rt,int l,int r){
37     flag[rt]=1;
38     if(l==r){
39         tr[rt]=arr[l];return;
40     }
41     int mid=(l+r)>>1;
42     build(lson);build(rson);
43     Pushup(rt);
44 }
45 void update(int rt,int l,int r,int L,int R){      //区间更新,维护一个区间标记,记录该区间是否需要改变
46     if(L<=l&&r<=R&&!flag[rt])return;     //如果这部分区间不需要修改,直接返回
47     if(l==r){
48         tr[rt]=facnum[tr[rt]];     //进行单点修改
49         if(tr[rt]==1||tr[rt]==2)flag[rt]=0;     //如果该点为1或2,那么该点就不用再修改了,因为1、2的因子个数仍然为1、2
50         return;
51     }
52     int mid=(l+r)>>1;
53     if(L<=mid&&flag[rt<<1])update(lson,L,R);
54     if(R>mid&&flag[rt<<1|1])update(rson,L,R);
55     Pushup(rt);
56 }
57 ll query(int rt,int l,int r,int L,int R){       //区间查询
58     if(L<=l&&r<=R)return tr[rt];
59     ll ans=0;
60     int mid=(l+r)>>1;
61     if(L<=mid)ans+=query(lson,L,R);
62     if(R>mid)ans+=query(rson,L,R);
63     return ans;
64 }    
65 int main(){
66     for(int i=1;i<=Max;i++)facnum[i]=Getfac(i);    //打表预处理得到1~1e6中所有的数的因子个数
67     read(n);read(q);
68     rep(i,1,n)read(arr[i]);
69     build(1,1,n);
70     while(q--){
71         int op,x,y;
72         read(op);read(x);read(y);
73         if(op==1)update(1,1,n,x,y);
74         else printf("%lld
",query(1,1,n,x,y));
75     }
76 }

2019-02-16

原文地址:https://www.cnblogs.com/00isok/p/10389286.html