[线段树]关于整段修改成a[i],并查询

主要解法

肯定要提前预留出di 数组,然后就是线段树。

刚开始以为 因子数=i-phi[i]+1

后来发现并不是,4和6不是因子关系,但是他们不是互质的,这两个的含义不一样, 并不是互补的

我们发现数据范围为1e6,然后一步步迭代 最终都会变成 1或者 2  d[1]=1  d[2]=2;  最多可迭代6次。

刚开始按照线段树一般解法,用Update 区间修改,是这点的话,就变成d[i],不是的话,就往下放,并且要push-up

查询用long long 

后来发现超时了,我们发现不是每次都需要往下放的,就比如 d[2]=d[d[2]],就没有任何意义。

我们用一个最大值来定义区间的最大值,如果最大值<=2,那么就不必往下放,节约时间。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <set>
 7 #include <map>
 8 #include <vector>
 9 #include <cctype>
10 #include <sstream>
11 using namespace std;
12 typedef long long ll;
13 const int inf=0x7fffffff;
14 const int N=1e6+100;
15 const int M=3*1e5+100;
16 ll tree[M<<2],d[N],mx[M<<2];
17 int n,m;
18 void init()
19 {
20     for(int i=1;i<N;i++)
21         for(int j=i;j<N;j+=i)
22             d[j]++;
23     //for(int i=1;i<=10;i++)
24     //    cout<<i<<" "<<d[i]<<endl;
25 }
26 void push_up(int rt)
27 {
28     tree[rt]=tree[rt<<1]+tree[rt<<1|1];
29     mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
30 }
31 void build(int rt,int l,int r)
32 {
33     if(l==r)
34     {
35         scanf("%lld",&tree[rt]);
36         mx[rt]=tree[rt];
37         return;
38     }
39     int m=(l+r)/2;
40     build(rt<<1,l,m);
41     build(rt<<1|1,m+1,r);
42     push_up(rt);
43 }
44 void update(int L,int R,int rt,int l,int r)
45 {
46     if(mx[rt]<=2)   return ;
47     if(l==r)
48     {
49         tree[rt]=mx[rt]=d[tree[rt]];
50         return ;
51     }
52     int m=(l+r)/2;
53     if(L<=m)    update(L,R,rt<<1,l,m);
54     if(R>m)     update(L,R,rt<<1|1,m+1,r);
55     push_up(rt);
56 }
57 ll query(int L,int R,int rt,int l,int r)
58 {
59     if(L<=l&&r<=R)  return tree[rt];
60     ll ans=0;
61     int m=(l+r)/2;
62     if(L<=m)    ans+=query(L,R,rt<<1,l,m);
63     if(R>m)     ans+=query(L,R,rt<<1|1,m+1,r);
64     return ans;
65 }
66 int main()
67 {
68     init();
69     scanf("%d %d",&n,&m);
70     build(1,1,n);
71     while(m--)
72     {
73         int k,l,r;
74         scanf("%d %d %d",&k,&l,&r);
75         if(k==1)
76             update(l,r,1,1,n);
77         else
78             cout<<query(l,r,1,1,n)<<endl;
79     }
80 
81     return 0;
82 }
View Code

解决这种题目的方法:

1.提前写出d[i]数组

2.线段树

3.看是否可以优化。

 

posted @ 2019-05-01 15:38  kaike  阅读(235)  评论(0编辑  收藏  举报