zoukankan      html  css  js  c++  java
  • AOJ 902 讨厌的“2” 【线段树】

    题面:

    有一个长度为n的数组a。现有m组操作。
    操作1:将区间[l,r]内的所有数字都整除2。
    操作2:输出区间[l,r]内所有数字的和。

    Input

    第一行输入两个整数n,m(1<=n<=200000,1<=m<=200000)
    第二行n个整数,表示数组a (0<=a[i]<=10^9)
    接下来m行,每行三个整数op,l,r
    ——若op=1,表示操作1,将[l,r]内所有数字整除2
    ——若op=2,表示操作2,输出[l,r]内所有数字的和
    Output
    对于所有的操作2,输出结果。

    Sample Input

    5 5

    3 4 9 2 7

    2 3 4

    1 4 5

    2 1 5

    1 3 4

    2 3 5

    Sample Output

    11

    20

    7

    大致思路:

    这个题是不能用lazytag的,因为整除不满足使用lazytag的条件。

    比如 对于序列1 3 5 7 9

    如果现在要求是 1 1 5

    然后求2 1 5

    真实答案是 10

    如果用lazytag标记的话答案就是12

    所以只能进行点修改。

    但也有可以优化的地方,如果一个区间的sum已经是0了,那么就没有必要继续递归修改了,因为0/2=0

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=2e5+7;
     4 int a[maxn];
     5 long long sum[maxn<<2];
     6 void maintain(int k)
     7 {
     8     sum[k]=sum[k<<1]+sum[k<<1|1];
     9 }
    10 void build(int l,int r,int k)
    11 {
    12     if(l>r)
    13         return ;
    14     if(l==r){
    15         sum[k]=a[l];
    16         return ;
    17     }
    18     int mid=(l+r)>>1;
    19     build(l,mid,k<<1);
    20     build(mid+1,r,k<<1|1);
    21     maintain(k);
    22 }
    23 void change(int l,int r,int cl,int cr,int k)
    24 {
    25     if(sum[k]==0)
    26         return ;
    27     if(l>r||cl>r||cr<l)
    28         return ;
    29     if(l==r){
    30         sum[k]=sum[k]/2;
    31         return ;
    32     }
    33 
    34     int mid=(l+r)>>1;
    35     change(l,mid,cl,cr,k<<1);
    36     change(mid+1,r,cl,cr,k<<1|1);
    37     maintain(k);
    38 }
    39 long long query(int l,int r,int ql,int qr,int k)
    40 {
    41     if(l>r||ql>r||qr<l)
    42         return 0;
    43     if(ql<=l&&qr>=r)
    44         return sum[k];
    45     if(sum[k]==0)
    46         return 0;
    47     int mid=(l+r)>>1;
    48     long long ans=0;
    49     ans=+query(l,mid,ql,qr,k<<1);
    50     ans+=query(mid+1,r,ql,qr,k<<1|1);
    51     return ans;
    52 }
    53 int main()
    54 {
    55     ios::sync_with_stdio(false);
    56     memset(sum,0,sizeof(sum));
    57     int n,m,cmd,l,r;
    58     cin>>n>>m;
    59     for(int i=1;i<=n;++i)
    60         cin>>a[i];
    61     build(1,n,1);
    62     for(int i=0;i<m;++i){
    63         cin>>cmd>>l>>r;
    64         if(cmd==1)
    65             change(1,n,l,r,1);
    66         else
    67             cout<<query(1,n,l,r,1)<<endl;
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    Linq分组后,再对分组后的每组数据进行排序,获取每组的第一条记录
    C/C++ 常量存储: 总结
    张庆科(山师大硕导简介) [转载]
    composer [packagist]包制作(入门篇)
    MMGCN: Multi-modal Graph Convolution Network for Personalized Recommendation of Micro-video
    opencv.js编译
    推荐
    推荐
    推荐
    Azure Automation (10) 在Automation中动态修改Azure Analysis Firewall防火墙规则
  • 原文地址:https://www.cnblogs.com/SCaryon/p/7419701.html
Copyright © 2011-2022 走看看