题意:

给一长度为n的序列,维护三个操作:区间开根,区间加,区间求和。

解法:

注意到本题关键在于区间开根:

对于一个数字,只要进行$O(loglogT)$次开根即会变为1。

考虑线段树,对于线段数上的点维护$maxv$,$minv$。

对于$[\sqrt{maxv}] = [\sqrt{minv}]$的点我们直接执行区间染色。

如果我们在开根时经过这个点则有$maxv - minv$减小,且只会经过$O(loglog(maxv-minv))$次。

考虑区间加的操作,相当于只是让$O(logn)$个位于 线段树上 修改区间边界上的两条链上的点 的$maxv-minv$增大,

这样会产生$O(logn*loglog(maxv-minv))$次的后续操作

注意到可能会出现开根后差值不变的情况,这样会导致 线段树上 修改区间内 的点的$maxv-minv$可能不变

导致效率退化。

特判一下,并将其转化为区间加上$\sqrt{maxv} - maxv$。

维护两个标记$addv$与$setv$,$setv$标记优先级大。

这样,总效率$O(nlogn*loglogn)$

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath> #define N 100010
#define LL long long
#define l(x) ch[x][0]
#define r(x) ch[x][1] using namespace std; int n,m,totn;
int a[N];
int ch[N<<][];
LL addv[N<<],maxv[N<<],minv[N<<],sumv[N<<],setv[N<<]; void push(int x,int l,int r)
{
if(l==r) return;
int mid=(l+r)>>;
LL lsiz = (mid-l+);
LL rsiz = (r-mid);
if(setv[x])
{
setv[l(x)]=setv[x];
maxv[l(x)]=setv[x];
minv[l(x)]=setv[x];
addv[l(x)]=;
sumv[l(x)]=lsiz*setv[x]; setv[r(x)]=setv[x];
maxv[r(x)]=setv[x];
minv[r(x)]=setv[x];
addv[r(x)]=;
sumv[r(x)]=rsiz*setv[x];
setv[x]=;
}
if(addv[x])
{
if(setv[l(x)]) setv[l(x)]+=addv[x];
else addv[l(x)]+=addv[x];
maxv[l(x)]+=addv[x];
minv[l(x)]+=addv[x];
sumv[l(x)]+=lsiz*addv[x]; if(setv[r(x)]) setv[r(x)]+=addv[x];
else addv[r(x)]+=addv[x];
maxv[r(x)]+=addv[x];
minv[r(x)]+=addv[x];
sumv[r(x)]+=rsiz*addv[x];
addv[x]=;
}
} void update(int x)
{
maxv[x] = max(maxv[l(x)], maxv[r(x)]);
minv[x] = min(minv[l(x)], minv[r(x)]);
sumv[x] = sumv[l(x)] + sumv[r(x)];
} int build(int l,int r)
{
int x=++totn;
addv[x]=;
setv[x]=;
if(l==r)
{
maxv[x]=a[l];
minv[x]=a[l];
sumv[x]=a[l];
return x;
}
int mid=(l+r)>>;
l(x)=build(l,mid);
r(x)=build(mid+,r);
update(x);
return x;
} void solve(int x,int l,int r)
{
push(x,l,r);
if(maxv[x]==) return;
LL tmp1 = (LL)sqrt(maxv[x]+0.5);
LL tmp2 = (LL)sqrt(minv[x]+0.5);
if(tmp1==tmp2)
{
setv[x]=tmp1;
maxv[x]=tmp1;
minv[x]=tmp1;
sumv[x]=(r-l+1LL)*tmp1;
return;
}
if(maxv[x]==minv[x]+ && tmp1==tmp2+)
{
addv[x]=tmp1-maxv[x];
maxv[x]+=addv[x];
minv[x]+=addv[x];
sumv[x]+=(r-l+1LL)*addv[x];
return;
}
int mid=(l+r)>>;
solve(l(x),l,mid);
solve(r(x),mid+,r);
update(x);
} void change(int x,int l,int r,int ql,int qr)
{
push(x,l,r);
if(ql<=l && r<=qr)
{
solve(x,l,r);
return;
}
int mid=(l+r)>>;
if(ql<=mid) change(l(x),l,mid,ql,qr);
if(mid<qr) change(r(x),mid+,r,ql,qr);
update(x);
} void add(int x,int l,int r,int ql,int qr,LL qv)
{
push(x,l,r);
if(ql<=l && r<=qr)
{
addv[x]=qv;
maxv[x]+=qv;
minv[x]+=qv;
sumv[x]+=qv*(r-l+1LL);
return;
}
int mid=(l+r)>>;
if(ql<=mid) add(l(x),l,mid,ql,qr,qv);
if(mid<qr) add(r(x),mid+,r,ql,qr,qv);
update(x);
} LL qsum(int x,int l,int r,int ql,int qr)
{
push(x,l,r);
if(ql<=l && r<=qr) return sumv[x];
int mid=(l+r)>>;
LL ans=;
if(ql<=mid) ans+=qsum(l(x),l,mid,ql,qr);
if(mid<qr) ans+=qsum(r(x),mid+,r,ql,qr);
update(x);
return ans;
} int main()
{
while(~scanf("%d%d",&n,&m))
{
totn=;
for(int i=;i<=n;i++) scanf("%d",&a[i]);
build(,n);
int cmd,l,r,x;
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&cmd,&l,&r);
if(cmd==)
{
scanf("%d",&x);
add(,,n,l,r,x);
}
else if(cmd==) change(,,n,l,r);
else printf("%lld\n",qsum(,,n,l,r));
}
}
return ;
}

Rikka with Sequence的更多相关文章

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

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

  2. 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence

    // 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...

  3. HDU 5828 Rikka with Sequence (线段树)

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

  4. hdu 5828 Rikka with Sequence 线段树

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

  5. hdu 5204 Rikka with sequence 智商不够系列

    Rikka with sequence Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...

  6. HDU 5828 Rikka with Sequence(线段树 开根号)

    Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

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

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

  8. HDU5828 Rikka with Sequence 线段树

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

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

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

  10. HDU 5828 Rikka with Sequence(线段树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5828 [题目大意] 给出一个数列,要求支持区间加法,区间开方和区间和查询操作. [题解] 考虑开方 ...

随机推荐

  1. VueJS样式绑定:v-bind

    HTML <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <titl ...

  2. django 运行python manage.py sqlall books 时报错 app has migration

    出现这个问题的原因是版本之前的不兼容,我用的django版本是1.8.6 而 这条python manage.py sqlall books 是基于django1.0版本的. 在django1.8.6 ...

  3. ZipOutputStream 用法 小计

    ZipOutputStream s = new ZipOutputStream(File.Create(ZipedFile)); 构造函数之后 文件就已经创建出来了 只是 0kb s.Write(bu ...

  4. 查看Laravel版本号的三种方法

    1:最简单的用命令行实现 php artisan --version 2:查看文件 vendor\laravel\framework\src\Illuminate\Foundation\Applica ...

  5. git 下载与Linux源码安装最新版

    win: https://git-for-windows.github.io/ 或 https://git-scm.com/downloads   官网!   源码安装git Git 的工作需要调用  ...

  6. 【caffe-windows】 caffe-master 之 卷积核可视化(利用matlab)

    此篇是利用matlab对caffemodel的卷积核进行可视化.只介绍了卷积核的可视化,不涉及特征图的可视化. 是参考此博客: http://blog.csdn.net/zb1165048017/ar ...

  7. 使用C#解决部分Win8.1系统窗体每隔几秒失去焦点的问题

    使用了Win8.1 With Update 1后,发现重新启动系统后,当前激活的窗体总是每隔几秒失去焦点.过0.5~1秒焦点回来.导致输入无法正常工作,严重影响使用心情和效率. 在网上找了非常久,也没 ...

  8. Python3做采集

    出于某些目的,需要在网上爬一些数据.考虑到Python有各种各样的库,以前想试试Pycharm这个IDE,就决定用它了.首先翻完<深入Python3>这本书,了解了它的语法之类的.下面就开 ...

  9. 一款很好的日程安排插件fullcalendar 非常适合OA等系统

    1.插件下载 http://arshaw.com/fullcalendar/download/ 2. <!DOCTYPE html> <meta http-equiv="C ...

  10. EL表达式 介绍

    EL表达式      1.EL简介 1)语法结构        ${expression} 2)[]与.运算符      EL 提供.和[]两种运算符来存取数据.      当要存取的属性名称中包含一 ...