• 刷题向》关于线段树的区间开根号 BZOJ3211(NORMAL+)


      这是一道关于线段树的区间开根号的裸题,没什么好讲的。

      值得注意的是,因为有区间开根号的性质,所以我们每一次更改操作只能把更改区间所覆盖的所有元素全部查找,当然你直接找效率明显爆炸。。。

      能够注意到,指数级别的操作一次更改的数字都很大,而题目的数字最大是10的9次,所以可以注意到的是当一个区间更新6遍以后就失去更新的意义了,因为当你更改次数超过6次所有非负整数数字就全部会化为1。所以可以在每一个节点上加一个类似于LAZY标记的东西,记录开根号次数,以便节约跟新时间。

      贴出题目&代码

    Description

     线段树区间开根号与求和

    Input

     第一行N代表有N个数
    第二行有N个数,代表这N个值分别是多少
    第三行有一个M
    接下来M行,每行有X,L,R
    当X为1代表求区间:(L,R)的和。
    当X为2代表对区间:(L,R)开根号。

    Output

    每次x=1时,每行一个整数,表示区间和

    Sample Input

    4
    1 100 5 5
    5
    1 1 2
    2 1 2
    1 1 2
    2 2 3
    1 1 4

    Sample Output

    101
    11
    11

    HINT

    对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9

     1 /**************************************************************
     2     Problem: 3211
     3     User: PencilWang
     4     Language: C++
     5     Result: Accepted
     6     Time:1996 ms
     7     Memory:9036 kb
     8 ****************************************************************/
     9  
    10 #include<cstdio>
    11 #include<cmath>
    12 int n,m;
    13 struct shit{
    14 int L,R,t;
    15 long long num;
    16 }s[400100];
    17 int w[100100];
    18 void push_up(int p)
    19 {
    20     s[p].num=s[p<<1].num+s[p<<1|1].num;
    21     return ;
    22 }
    23 void build(int p,int l,int r)
    24 {
    25     s[p].L=l;
    26     s[p].R=r;
    27     if(l==r)
    28     {
    29     s[p].num=w[l];
    30     return ;
    31     }
    32     int mid=(l+r)>>1;
    33     build(p<<1,l,mid);
    34     build(p<<1|1,mid+1,r);
    35     push_up(p);
    36     return ;
    37 }
    38 void fuck(int p,int a,int b)
    39 {
    40     if(a<=s[p].L&&s[p].R<=b)
    41     {
    42         s[p].t++;
    43         if(s[p].L==s[p].R)
    44         {
    45             s[p].num=sqrt(s[p].num);
    46             return ;
    47         }
    48     }
    49     int mid=(s[p].L+s[p].R)>>1;
    50     if(s[p<<1].t<6&&a<=mid)fuck(p<<1,a,b);
    51     if(s[p<<1|1].t<6&&b>mid)fuck(p<<1|1,a,b);
    52     push_up(p);
    53     return ;
    54 }
    55 long long Q(int p,int a,int b)
    56 {
    57     if(a<=s[p].L&&s[p].R<=b)
    58     {
    59     return s[p].num;
    60     }
    61     long long ans=0;
    62     int mid=(s[p].L+s[p].R)>>1;
    63     if(a<=mid) ans+=Q(p<<1,a,b);
    64     if(b>mid)ans+=Q(p<<1|1,a,b);
    65     return ans;
    66 }
    67 int main()
    68 {
    69     int a,b,f;
    70     scanf("%d",&n);
    71     for(int i=1;i<=n;i++)scanf("%d",w+i);
    72     scanf("%d",&m);
    73     build(1,1,n);
    74     while(m--)
    75     {
    76     scanf("%d%d%d",&f,&a,&b);
    77     if(f-1)fuck(1,a,b);
    78     else printf("%lld
    ",Q(1,a,b));
    79     }
    80     return 0;
    81 }
    3211

  • 相关阅读:
    OpenCV人脸检测
    和机器学习和计算机视觉相关的数学(转载)
    操作系统课程设计 消息缓冲队列通信
    操作系统课程设计 线程的同步与互斥
    嵌入式考试Shell编程题
    Bash基础知识
    开始学习Shell/bash 加减乘运算
    RT-Thread Mini2440串口驱动
    Mini2440裸机RTC时钟驱动转化为字符串显示
    Mini2440裸机液晶屏TD35驱动
  • 原文地址:https://www.cnblogs.com/PencilWang/p/5958812.html
Copyright © 2020-2023  润新知