zoukankan      html  css  js  c++  java
  • [线段树]关于整段修改成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.看是否可以优化。

    No matter how you feel, get up , dress up , show up ,and never give up.
  • 相关阅读:
    weblogic12c 2021.4.20 季度补丁 SPB
    一顿debug猛如虎,原来内存OOM
    JDK记录一下
    213. 打家劫舍 II-动态规划-中等
    5526. 最多可达成的换楼请求数目-回溯-困难
    1584. 连接所有点的最小费用-图/最小生成树-中等
    Java-泛型的限制
    Java-泛型-桥方法
    889. 根据前序和后序遍历构造二叉树-树-中等
    1109. 航班预订统计-差分数组-中等
  • 原文地址:https://www.cnblogs.com/Kaike/p/10799960.html
Copyright © 2011-2022 走看看