题意:

给一长度为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. 轻松搞定RabbitMQ(六)——主题

    转自 http://blog.csdn.net/xiaoxian8023/article/details/48806871 翻译地址:http://www.rabbitmq.com/tutorials ...

  2. website link

    error: template with C linkage http://blog.csdn.net/jiong_1988/article/details/7915420http://velep.c ...

  3. canvas 橡皮擦效果制作

    擦除一定数量后全部消失的有用 imageData 方法的 我把代码贴在最下面 <!DOCTYPE html> <html> <head> <meta char ...

  4. 用python模拟TCP3次握手连接及发送数据

    源码如下: from scapy.all import * import logging logging.getLogger('scapy.runtime').setLevel(logging.ERR ...

  5. HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

    题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出相应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  相应区间的LCIS长度(lcis)  相应区间以左 ...

  6. 常用PHP MySQL函数

    配置选项 MySQL 函数的行为受到 php.ini 中设置的影响. mysql.allow_persistent "1" 是否允许 MySQL 的持久连接. mysql.max_ ...

  7. C# wince 实现软件忙鼠标状态改变

    eg: Cursor.Current = Cursors.WaitCursor; dosomething(); Cursor.Current = Cursors.Default; Cursor.Cur ...

  8. Spring注入service为null另类解决办法 工具类 一般类 静态 非controller

    系统为SpringMVC框架,在开发的过程中有一些工具类需要调用下由spring管理的service层.但是一进注入不进来,报null异常: 在尝试了网上的一系列方法后,还是没有解决.网上的解决方法主 ...

  9. hdu 3415 单调队列

    Max Sum of Max-K-sub-sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  10. SpringBoot-(5)-properties的使用

    项目中经常需要进行一些配置,一般会使用springboot默认的application.properties文件,也可以自己创建配置文件 一,application.properties配置 logg ...