传送门

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

线段树常规操作。

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

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

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

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

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

所以怎么做呢?

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

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

这样的话,我们维护区间最大值和区间最小值,如果当前区间的最大值与最小值的差不大于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. 可视化库-seaborn-热力图(第五天)

    1. 画一个基本的热力图, 通过热力图用来观察样本的分布情况 import matplotlib.pyplot as plt import numpy as np np.random.seed(0) ...

  2. c++ cout cin, 命名空间

    cout<<a<<endl; cout<<a; 返回值其实就是一个输出流,(cout就是输出流) 上述语句等价于(cout<<a)<<end ...

  3. event bManualResult

    MSDN: bManualReset [in] If this parameter is TRUE, the function creates a manual-reset event object, ...

  4. How to Pronounce WH Words — what, why, which

    How to Pronounce WH Words — what, why, which Share Tweet Share Have you noticed that there are two d ...

  5. 基于 tensorflow 的 mnist 数据集预测

    1. tensorflow 基本使用方法 2. mnist 数据集简介与预处理 3. 聚类算法模型 4. 使用卷积神经网络进行特征生成 5. 训练网络模型生成结果 how to install ten ...

  6. cookie保存用户名及密码

    登陆页中,用户输入用户名密码,点击提交,后台对照mysq数据库中,看是否有对应的用户名,以及密码是否正确.如果正确 则将用户名密码分两份Cookie保存.页面跳转到登陆成功页. 用户再次访问登陆页时, ...

  7. Access denied for user 'root'@'localhost' (using password:YES)解决方法

    Access denied for user 'root'@'localhost' (using password:YES)解决方法 在MySQL的使用过程中,我们可能会碰到“Access denie ...

  8. pipeenv error

    [root@mhc tmp]# pipenv --python 3.6Creating a virtualenv for this project…Using /root/python3/bin/py ...

  9. easyui input未设id导致的问题

    今天又踩了一个坑,大致是没有给input设id,使用类选择器绑定easyui控件,然后使用name设值,现在值设进去后界面没有显示. 做的界面部分截图如图: 点击下面两个橙色的按钮,通过调用下面的方法 ...

  10. Android 最火开发框架 xUtils

    xUtils简介 xUtils3 api变化较多, 已转至 https://github.com/wyouflf/xUtils3 xUtils 2.x对Android 6.0兼容不是很好, 请尽快升级 ...