传送门

这道题维护区间加,区间开根,区间求和。

线段树常规操作。

首先回忆两道简单得多的线段树。

第一个:区间覆盖,区间加,区间求和。

第二个:区间开根,区间求和。

这两个是名副其实的常规操作。

但这道题如果学习没有区间加的做法维护最大值很容易卡掉。

所以怎么做呢?

区间加和区间求和就略了。

考虑到开根的性质,显然一段区间的数多开几次根差就不大了。

这样的话,我们维护区间最大值和区间最小值,如果当前区间的最大值与最小值的差不大于1的话就直接进行开根操作,否则继续递归。

开根时要分类讨论。

我们令fx=sqrt(max)" role="presentation" style="position: relative;">fx=sqrt(max)fx=sqrt(max),fy=sqrt(min)" role="presentation" style="position: relative;">fy=sqrt(min)fy=sqrt(min),就有两种情况。

第一种:fx==fy" role="presentation" style="position: relative;">fx==fyfx==fy,那么这相当于区间覆盖。

第二种:fx==fy+1" role="presentation" style="position: relative;">fx==fy+1fx==fy+1,那么显然有max−min==1" role="presentation" style="position: relative;">max−min==1max−min==1,所以推出max−fx==min−fy" role="presentation" style="position: relative;">max−fx==min−fymax−fx==min−fy,所以就成了一个区间加操作(只是加了一个非负数)。这就转化成了第一个基础线段树的操作了。

代码如下:

#include<bits/stdc++.h>
#include<bits/stdc++.h>
#define N 100005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define ll long long
using namespace std;
inline ll read(){
    ll ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
inline void write(ll x){
    if(x>9)write(x/10);
    putchar((x%10)^48);
}
int n,m,T_T;
ll a[N];
inline ll max(ll a,ll b){return a>b?a:b;}
inline ll min(ll a,ll b){return a<b?a:b;}
struct Node{int l,r;ll maxn,minn,sum,lz,bz;}T[N<<2];
inline void pushup(int p){T[p].maxn=max(T[lc].maxn,T[rc].maxn),T[p].minn=min(T[lc].minn,T[rc].minn),T[p].sum=T[lc].sum+T[rc].sum;}
inline void pushnow(int p,ll v){T[p].sum+=(T[p].r-T[p].l+1)*v,T[p].lz+=v,T[p].maxn+=v,T[p].minn+=v;}
inline void pushnown(int p,ll v){T[p].lz=0;T[p].sum=(T[p].r-T[p].l+1)*v,T[p].bz=T[p].maxn=T[p].minn=v;}
inline void pushdown(int p){
    if(T[p].bz!=-1)pushnown(lc,T[p].bz),pushnown(rc,T[p].bz),T[p].bz=-1;
    if(T[p].lz)pushnow(lc,T[p].lz),pushnow(rc,T[p].lz),T[p].lz=0;
}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r,T[p].lz=0,T[p].bz=-1;
    if(l==r){T[p].maxn=T[p].minn=T[p].sum=a[l];return;}
    build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,ll v){
    if(ql>T[p].r||qr<T[p].l)return;
    if(ql<=T[p].l&&T[p].r<=qr){pushnow(p,v);return;}
    pushdown(p);
    if(qr<=mid)update(lc,ql,qr,v);
    else if(ql>mid)update(rc,ql,qr,v);
    else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
    pushup(p);
}
inline void modify(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return;
    if(ql<=T[p].l&&T[p].r<=qr&&T[p].maxn-T[p].minn<=1){
        ll fx=sqrt(T[p].maxn),fy=sqrt(T[p].minn);
        if(fx==fy)pushnown(p,fx);
        else pushnow(p,fx-T[p].maxn);
        return;
    }
    pushdown(p);
    if(qr<=mid)modify(lc,ql,qr);
    else if(ql>mid)modify(rc,ql,qr);
    else modify(lc,ql,mid),modify(rc,mid+1,qr);
    pushup(p);
}
inline ll query(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return 0;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].sum;
    pushdown(p);
    if(qr<=mid)return query(lc,ql,qr);
    if(ql>mid)return query(rc,ql,qr);
    return query(lc,ql,mid)+query(rc,mid+1,qr);
}
int main(){
    T_T=read();
    while(T_T--){
        n=read(),m=read();
        for(int i=1;i<=n;++i)a[i]=read();
        build(1,1,n);
        while(m--){
            int op=read(),l=read(),r=read();
            switch(op){
                case 1:{ll v=read();update(1,l,r,v);break;}
                case 2:{modify(1,l,r);break;}
                default:{write(query(1,l,r)),puts("");break;}
            }
        }
    }
    return 0;
}

2018.07.23 hdu5828 Rikka with Sequence(线段树)的更多相关文章

  1. HDU5828 Rikka with Sequence 线段树

    分析:这个题和bc round 73应该是差不多的题,当时是zimpha巨出的,那个是取phi,这个是开根 吐槽:赛场上写的时候直接维护数值相同的区间,然后1A,结果赛后糖教一组数据给hack了,仰慕 ...

  2. 2016暑假多校联合---Rikka with Sequence (线段树)

    2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...

  3. hdu 5828 Rikka with Sequence 线段树

    Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...

  4. 2018.07.08 hdu6183 Color it(线段树)

    Color it Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) Proble ...

  5. HDU 5828 Rikka with Sequence(线段树区间加开根求和)

    Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...

  6. HDU 5828 Rikka with Sequence (线段树+剪枝优化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...

  7. 2018.07.08 POJ 2481 Cows(线段树)

    Cows Time Limit: 3000MS Memory Limit: 65536K Description Farmer John's cows have discovered that the ...

  8. HDU5634 Rikka with Phi 线段树

    // HDU5634 Rikka with Phi 线段树 // 思路:操作1的时候,判断一下当前区间是不是每个数都相等,在每个数相等的区间上操作.相当于lazy,不必更新到底. #include & ...

  9. 2018.07.23 codeforces 438D. The Child and Sequence(线段树)

    传送门 线段树维护区间取模,单点修改,区间求和. 这题老套路了,对一个数来说,每次取模至少让它减少一半,这样每次单点修改对时间复杂度的贡献就是一个log" role="presen ...

随机推荐

  1. delphi 泛型 c++builder 泛型

    delphi 泛型 System.Generics.Collections.pas TList<T> http://docwiki.embarcadero.com/Libraries/Be ...

  2. padding 扩大边距 margin-top 与页面顶部的距离 hover鼠标移动到上面出现背景色CSS

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. ABAP-动态ALV

    1.参数定义 "ALV type-pools:slis,rsds,vrm. data:gt_fieldcat type lvc_t_fcat with header line, gt_eve ...

  4. ABAP-ITS Mobile

    ITS Mobile是14年开发EWM项目时用到的技术方案,本文主要记录下ITS Mobile的整个实现过程. 1.ITS Mobile介绍 ITS Mobile:Internet Transacti ...

  5. scala-学习 2

    列表操作 List() 或者是 Nil 空list scala> val a = List() a:List[Nothing] = List() print(a.length) a.length ...

  6. git 拉取某个分支到本地

    git 拉取其实只需要 git fetch origin xxx. git pull origin xxx即可

  7. ArcGIS案例学习1_2

    ArcGIS案例学习1_2 联系方式:谢老师,135_4855_4328, xiexiaokui#qq.com 时间:第一天下午 案例1:矢量提取,栅格提取和坐标系投影变换 目的:认识数据类型 教程: ...

  8. js json转对象

    使用eval() 读取 for (var i=0;i< response.length; i++) { //alert(response[i].username) html=html+" ...

  9. pymongo CursorNotFound错误

    部分报错如下: File "D:\anaconda\lib\site-packages\pymongo\cursor.py", line 1189, in next if len( ...

  10. Windows phone自定义控件(无外观控件)——FlipPanel

    编码前 无外观自定义控件的定义在上一篇中已经有了,至于这一篇的自定义控件,比之前多加入了状态的变化,就像默认的Button具有Pressed.Normal等状态.在状态转变的同时可以加上一些动画,可以 ...