Rikka with Sequence
题意:
给一长度为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的更多相关文章
- 2016暑假多校联合---Rikka with Sequence (线段树)
2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...
- 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence
// 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...
- HDU 5828 Rikka with Sequence (线段树)
Rikka with Sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- hdu 5828 Rikka with Sequence 线段树
Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- hdu 5204 Rikka with sequence 智商不够系列
Rikka with sequence Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...
- HDU 5828 Rikka with Sequence(线段树 开根号)
Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- HDU 5828 Rikka with Sequence(线段树区间加开根求和)
Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...
- HDU5828 Rikka with Sequence 线段树
分析:这个题和bc round 73应该是差不多的题,当时是zimpha巨出的,那个是取phi,这个是开根 吐槽:赛场上写的时候直接维护数值相同的区间,然后1A,结果赛后糖教一组数据给hack了,仰慕 ...
- HDU 5828 Rikka with Sequence (线段树+剪枝优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...
- HDU 5828 Rikka with Sequence(线段树)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5828 [题目大意] 给出一个数列,要求支持区间加法,区间开方和区间和查询操作. [题解] 考虑开方 ...
随机推荐
- VueJS样式绑定:v-bind
HTML <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <titl ...
- django 运行python manage.py sqlall books 时报错 app has migration
出现这个问题的原因是版本之前的不兼容,我用的django版本是1.8.6 而 这条python manage.py sqlall books 是基于django1.0版本的. 在django1.8.6 ...
- ZipOutputStream 用法 小计
ZipOutputStream s = new ZipOutputStream(File.Create(ZipedFile)); 构造函数之后 文件就已经创建出来了 只是 0kb s.Write(bu ...
- 查看Laravel版本号的三种方法
1:最简单的用命令行实现 php artisan --version 2:查看文件 vendor\laravel\framework\src\Illuminate\Foundation\Applica ...
- git 下载与Linux源码安装最新版
win: https://git-for-windows.github.io/ 或 https://git-scm.com/downloads 官网! 源码安装git Git 的工作需要调用 ...
- 【caffe-windows】 caffe-master 之 卷积核可视化(利用matlab)
此篇是利用matlab对caffemodel的卷积核进行可视化.只介绍了卷积核的可视化,不涉及特征图的可视化. 是参考此博客: http://blog.csdn.net/zb1165048017/ar ...
- 使用C#解决部分Win8.1系统窗体每隔几秒失去焦点的问题
使用了Win8.1 With Update 1后,发现重新启动系统后,当前激活的窗体总是每隔几秒失去焦点.过0.5~1秒焦点回来.导致输入无法正常工作,严重影响使用心情和效率. 在网上找了非常久,也没 ...
- Python3做采集
出于某些目的,需要在网上爬一些数据.考虑到Python有各种各样的库,以前想试试Pycharm这个IDE,就决定用它了.首先翻完<深入Python3>这本书,了解了它的语法之类的.下面就开 ...
- 一款很好的日程安排插件fullcalendar 非常适合OA等系统
1.插件下载 http://arshaw.com/fullcalendar/download/ 2. <!DOCTYPE html> <meta http-equiv="C ...
- EL表达式 介绍
EL表达式 1.EL简介 1)语法结构 ${expression} 2)[]与.运算符 EL 提供.和[]两种运算符来存取数据. 当要存取的属性名称中包含一 ...