传送门

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

线段树常规操作。

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

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

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

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

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

所以怎么做呢?

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

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

这样的话,我们维护区间最大值和区间最小值,如果当前区间的最大值与最小值的差不大于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. border做三角符号

    用border做三角符号以及其他图形 ;; border-width:20px 10px; border-style:solid; border-color:#ff3300 #ff3300 #ffff ...

  2. js--语音播报

    一.借用百度接口 function speckText(){ var str = "请及时预警!"; //var request= new URLRequest(); var ur ...

  3. 【转】vc api 录音

    一.数字音频基础知识 Fourier级数: 任何周期的波形可以分解成多个正弦波,这些正弦波的频率都是整数倍.级数中其他正线波的频率是基础频率的整数倍.基础频率称为一级谐波. PCM: pulse co ...

  4. 程序员教程-10章-C++程序设计

    本来这章是不打算写了的,毕竟自己学的是JAVA,C++就不想看了,但毕竟还有一点时间,就把C++也看一下吧 目录结构 10.1 C++程序基础 10.1.1 数据类型 1 基本数据类型 2 常量和变量 ...

  5. C++之继承与多态

    在程序设计领域,一个广泛认可的定义是“一种将不同的特殊行为和单个泛化记号相关联的能力”.和纯粹的面向对象程序设计语言不同,C++中的多态有着更广泛的含义.除了常见的通过类继承和虚函数机制生效于运行期的 ...

  6. spring浏览器国际化的原理

    We will add two languages support to our application: English and German. Depending on the locale se ...

  7. 迷你MVVM框架 avalonjs 学习教程18、一步步做一个todoMVC

    大凡出名的MVC,MVVM框架都有todo例子,我们也搞一下看看avalon是否这么便宜. 我们先从react的todo例子中扒一下HTML与CSS用用. <!doctype html> ...

  8. javascript中this之说

    this是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象.不过,匿名函数的执行环境具有全局性,因此其this对象通常 ...

  9. vim使用方法:

    vim使用方法: 模式: 编辑模式.未编辑模式.命令行模式 i 插入形式进入编辑模式 a 增加 o 下行编辑 O 上行插入 : 进入命令行模式 esc 退出编辑模式 wq 保存文件 yy 复制 p 粘 ...

  10. post与get的区别

    GET请求在URL中传送的参数大多数浏览器限制该长度为2kb的,而POST没有. GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息. GET参数通过URL传递,POST放 ...