题意:

给一长度为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. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  2. OI知识体系

  3. Qt在线讲座之QML脚本书写规范

    时间:2016年3月1日晚7:30 在线讲座:http://qtdream.com主页处就可以收看直播(详见主页提示) 參与对象:对Qt跨平台开发框架感兴趣的朋友们.当然了,假设你是大牛.也可以旁听一 ...

  4. ANDROID STUDIO 2.2.3 DOWNLOAD FROM DL.GOOGLE.COM

    立即开始使用 Android Studio Android Studio 包含用于构建 Android 应用所需的所有工具. 下载 ANDROID STUDIO2.2.3 FOR WINDOWS (1 ...

  5. 成长为 iOS 大 V 的秘密

    成长为 iOS 大 V 的秘密   前言 毫不谦虚地说,我是国内 iOS 开发的大 V.我从 2011 年底开始自学 iOS 开发,经过 3 年时间,到 2014 年底,我不但写作了上百篇 iOS 相 ...

  6. 【TensorFlow-windows】(零)TensorFlow的"安装"

    Tensorflow的安装,具体操作就不演示了.具体操作请移步: http://blog.csdn.net/darlingwood2013/article/details/60322258#comme ...

  7. 【MatConvNet】配置GPU

    参照大神的方法:http://www.th7.cn/system/win/201603/155182.shtml 第一步:需要安装cuda.VS2013:cuda默认路径,注意cuda版本和GPU要匹 ...

  8. OpenCV 入门示例之一:显示图像

    前言 本文展示一个显示图像的示例程序,它用于从硬盘加载一副图像并在屏幕上显示. 代码示例 // 此头文件包含图像IO函数的声明 #include "highgui.h" int m ...

  9. session.use_cookies有什么作用,

    session.use_cookies有什么作用, @ini_set('session.use_cookies', 1);什么意思 若session.use_cookies = 1 sessionid ...

  10. 1185: [HNOI2007]最小矩形覆盖

    1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1426  Solve ...