• cf920F SUM and REPLACE 树状数组+set 维护


    题目:

    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) = 4 (6 is divisible by 1, 2, 3 and 6).

    You are given an array a of n integers. You have to process two types of queries:

    1. REPLACE l r — for every  replace ai with D(ai);
    2. SUM l r — calculate .

    Print the answer for each SUM query.

    分析:

    我们考虑到每个数可以进行操作的数量不会很多,且D(1)=1,D(2)=2.

    我们只需要暴力修改就行了,然后用树状数组求和.

    如何优雅的暴力?

    也就是说如何快速找出区间[l,r]内满足ai>2的i值.考虑用set维护还可以操作的下标的点,每次用lb,ub去找.暴力修改.

    另外筛1-1e6中每个数的因子个数的方法需要注意.

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int MAXN=3e5+7;
     5 int N,M;
     6 LL a[MAXN],val[MAXN];
     7 int D[1000001];
     8 inline int lowbit(int i){
     9     return i&-i;
    10 }
    11 LL sum(int x){
    12     LL res=0;
    13     while(x){
    14         res+=a[x];
    15         x-=lowbit(x);
    16     }
    17     return res;
    18 }
    19 void add(int i,int x){
    20     while(i<=N){
    21         a[i]+=x;
    22         i+=lowbit(i);
    23     }
    24 }
    25 int getD(long long x){
    26     return D[x];
    27 }
    28 int main(){
    29     for(int i=1;i<=1000000;++i){
    30         for(int j=i;j<=1000000;j+=i){
    31             D[j]++;
    32         }
    33     }
    34     scanf("%d%d",&N,&M);
    35     set<int>st;
    36     for(int i=1;i<=N;++i){
    37         scanf("%I64d",&val[i]);
    38         if(val[i]>2)st.insert(i);
    39         add(i,val[i]);
    40     }
    41     while(M--){
    42         int t,l,r;scanf("%d%d%d",&t,&l,&r);
    43         if(t==1){
    44             auto first=st.lower_bound(l);
    45             auto last=st.upper_bound(r);
    46             queue<int>q;
    47             while(first!=last){
    48                 int i=*first;
    49                 int x=getD(val[i]);
    50                 add(i,x-val[i]);
    51                 val[i]=x;
    52                 if(x<=2)q.push(i);
    53                 first++;
    54             }
    55             while(!q.empty()){
    56                 int now=q.front();q.pop();
    57                 st.erase(now);
    58             }
    59         }else{
    60             printf("%I64d
    ",sum(r)-sum(l-1));
    61         }
    62     }
    63     return 0;
    64 }
    View Code
  • 相关阅读:
    sql round
    COJ1086 分组01背包
    POJ3624 (01背包)
    COJ1271 Brackets Sequence
    nacoskubernet集群安装(离线安装)
    docker离线安装及本地yum配置
    rediskubernet集群离线安装
    mysql修改密码
    harbor离线安装
    ansibletidb3.0安装(离线版)
  • 原文地址:https://www.cnblogs.com/sun-yinkai/p/8417093.html
Copyright © 2020-2023  润新知