zoukankan      html  css  js  c++  java
  • HDU 5828 Rikka with Sequence(线段树区间加开根求和)

    Problem Description
    As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

    Yuta has an array A with n numbers. Then he makes m operations on it.

    There are three type of operations:

    1 l r x : For each i in [l,r], change A[i] to A[i]+x
    2 l r : For each i in [l,r], change A[i] to ⌊√A[i]⌋
    3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r]

    It is too difficult for Rikka. Can you help her?

    Input
    The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000.

    For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.

    It is guaranteed that 1<=A[i],x<=100000.

    Output
    For each operation of type 3, print a lines contains one number -- the answer of the query.

    Sample Input
    1
    5 5
    1 2 3 4 5
    1 3 5 2
    2 1 4
    3 2 4
    2 3 5
    3 1 5

    Sample Output
    5
    6

    题意

    实现区间加,区间开根,区间求和

    题解

    一开始以为可以暴力开根,然后统计区间内是否全为1,后来发现开完根再加又可以开根所以单次复杂度就变成O(n)

     后来发现区间开根会出现一大片相同的区域,所以可以再维护一个最大最小值,如果maxx[rt]-minn[rt]==(LL)sqrt(maxx[rt])-(LL)sqrt(minn[rt])||maxx[rt]==minn[rt]就说明区间开根后所有值都相同,那就可以直接更新区间

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define LL long long
      5 
      6 const int maxn=1e5+5;
      7 
      8 LL sum[maxn<<2],lazy[maxn<<2],minn[maxn<<2],maxx[maxn<<2];
      9 
     10 void pushdown(int l,int r,int rt)
     11 {
     12     if(lazy[rt]==0)return;
     13     lazy[rt<<1]+=lazy[rt];
     14     lazy[rt<<1|1]+=lazy[rt];
     15     int mid=(l+r)>>1;
     16     sum[rt<<1]+=lazy[rt]*(mid-l+1);
     17     sum[rt<<1|1]+=lazy[rt]*(r-mid);
     18     maxx[rt<<1]+=lazy[rt];
     19     maxx[rt<<1|1]+=lazy[rt];
     20     minn[rt<<1]+=lazy[rt];
     21     minn[rt<<1|1]+=lazy[rt];
     22     lazy[rt]=0;
     23 }
     24 void pushup(int rt)
     25 {
     26     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
     27     minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
     28     maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
     29 }
     30 void build(int l,int r,int rt)
     31 {
     32     lazy[rt]=0;
     33     if(l==r)
     34     {
     35         scanf("%lld",&sum[rt]);
     36         minn[rt]=maxx[rt]=sum[rt];
     37         return;
     38     }
     39     int mid=(l+r)>>1;
     40     build(l,mid,rt<<1);
     41     build(mid+1,r,rt<<1|1);
     42     pushup(rt);
     43 }
     44 void update(int L,int R,LL C,int l,int r,int rt)
     45 {
     46     if(L<=l&&r<=R)
     47     {
     48         lazy[rt]+=C;
     49         sum[rt]+=(r-l+1)*C;
     50         maxx[rt]+=C;
     51         minn[rt]+=C;
     52         return;
     53     }
     54     int mid=(l+r)>>1;
     55     pushdown(l,r,rt);
     56     if(L<=mid)update(L,R,C,l,mid,rt<<1);
     57     if(R>mid)update(L,R,C,mid+1,r,rt<<1|1);
     58     pushup(rt);
     59 }
     60 void Sqrt(int L,int R,int l,int r,int rt)
     61 {
     62     if(L<=l&&r<=R)
     63     {
     64         if(maxx[rt]-minn[rt]==(LL)sqrt(maxx[rt])-(LL)sqrt(minn[rt])||maxx[rt]==minn[rt])
     65         {
     66             LL z=(LL)sqrt(maxx[rt])-maxx[rt];
     67             sum[rt]+=z*(r-l+1);
     68             maxx[rt]+=z,minn[rt]+=z,lazy[rt]+=z;
     69             return;
     70         }
     71     }
     72     int mid=(l+r)>>1;
     73     pushdown(l,r,rt);
     74     if(L<=mid)Sqrt(L,R,l,mid,rt<<1);
     75     if(R>mid)Sqrt(L,R,mid+1,r,rt<<1|1);
     76     pushup(rt);
     77 }
     78 LL query(int L,int R,int l,int r,int rt)
     79 {
     80     if(L<=l&&r<=R)
     81         return sum[rt];
     82     int mid=(l+r)>>1;
     83     LL ans=0;
     84     pushdown(l,r,rt);
     85     if(L<=mid)ans+=query(L,R,l,mid,rt<<1);
     86     if(R>mid)ans+=query(L,R,mid+1,r,rt<<1|1);
     87     pushup(rt);
     88     return ans;
     89 }
     90 int main()
     91 {
     92     int t,n,m;
     93     scanf("%d",&t);
     94     while(t--)
     95     {
     96         scanf("%d%d",&n,&m);
     97         build(1,n,1);
     98         for(int i=0;i<m;i++)
     99         {
    100             int op,l,r;
    101             LL x;
    102             scanf("%d%d%d",&op,&l,&r);
    103             if(op==1)
    104             {
    105                 scanf("%lld",&x);
    106                 update(l,r,x,1,n,1);
    107             }
    108             else if(op==2)
    109             {
    110                 Sqrt(l,r,1,n,1);
    111             }
    112             else if(op==3)
    113             {
    114                 printf("%lld
    ",query(l,r,1,n,1));
    115             }
    116         }
    117     }
    118     return 0;
    119 }
    120 /*
    121 1
    122 5 10
    123 1 2 3 4 5
    124 1 1 3 10
    125 2 1 3
    126 2 1 3
    127 2 1 3
    128 2 1 3
    129 3 1 3
    130 */
  • 相关阅读:
    wpf 资源
    九宫格扩展,输入一个奇数,得到横竖斜相加相等结果
    安装IIS的convlog.exe问题
    Windows API
    使用快捷键弹出新对话框
    数据结构笔试(转)
    运算符重载
    宽字节与多字节转换
    C++之乱七八糟<真正的随笔>
    MFC调用ActiveX
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/9842379.html
Copyright © 2011-2022 走看看