【uoj#228】基础数据结构练习题 线段树+均摊分析
给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有三种:区间加、区间开根、区间求和。
$n,m,a_i\le 100000$ 。
题解
线段树+均摊分析
对于原来的两个数 $a$ 和 $b$ ( $a>b$ ) ,开根后变成 $\sqrt a$ 和 $\sqrt b$ ,它们的差从 $a-b$ 变成了 $\sqrt a-\sqrt b$ 。
又有 $(\sqrt a-\sqrt b)(\sqrt a+\sqrt b)=a-b$ ,因此开方后的差小于原来差的开方。
而当区间差为 $0$ 或 $a=x^2,b=x^2-1$ 的 $1$ 时,区间开根就变成了区间减。
因此一个区间开根 $\log\log(Max-Min)$ 次后就不需要暴力开根,直接区间减即可。
定义线段树节点势能为 $\log\log(Max-Min)$ ,那么每次对 $[l,r]$ 开根就是将所有 $l\le x,y\le r$ ,且势能不为 $0$ 的节点 $[x,y]$ 的势能减 $1$ ,代价为势能减少总量。
分析区间加操作:只会修改到经过的节点的势能,影响 $\log$ 个节点,将这些点的势能恢复为 $\log\log(Max-Min)$ 。
因此总的时间复杂度就是总势能量 $O((n+m\log n)\log\log a)$ 。
#include <cmath>
#include <cstdio>
#include <algorithm>
#define N 100010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
typedef long long ll;
ll sum[N << 2] , mx[N << 2] , mn[N << 2] , tag[N << 2];
inline void add(ll v , int l , int r , int x)
{
sum[x] += v * (r - l + 1) , mx[x] += v , mn[x] += v , tag[x] += v;
}
inline void pushup(int x)
{
sum[x] = sum[x << 1] + sum[x << 1 | 1];
mx[x] = max(mx[x << 1] , mx[x << 1 | 1]);
mn[x] = min(mn[x << 1] , mn[x << 1 | 1]);
}
inline void pushdown(int l , int r , int x)
{
if(tag[x])
{
int mid = (l + r) >> 1;
add(tag[x] , lson) , add(tag[x] , rson);
tag[x] = 0;
}
}
inline void build(int l , int r , int x)
{
if(l == r)
{
scanf("%lld" , &sum[x]) , mx[x] = mn[x] = sum[x];
return;
}
int mid = (l + r) >> 1;
build(lson) , build(rson);
pushup(x);
}
inline void update(int b , int e , ll a , int l , int r , int x)
{
if(b <= l && r <= e)
{
add(a , l , r , x);
return;
}
pushdown(l , r , x);
int mid = (l + r) >> 1;
if(b <= mid) update(b , e , a , lson);
if(e > mid) update(b , e , a , rson);
pushup(x);
}
inline void change(int b , int e , int l , int r , int x)
{
if(b <= l && r <= e && mx[x] - (ll)sqrt(mx[x]) == mn[x] - (ll)sqrt(mn[x]))
{
add((ll)sqrt(mx[x]) - mx[x] , l , r , x);
return;
}
pushdown(l , r , x);
int mid = (l + r) >> 1;
if(b <= mid) change(b , e , lson);
if(e > mid) change(b , e , rson);
pushup(x);
}
inline ll query(int b , int e , int l , int r , int x)
{
if(b <= l && r <= e) return sum[x];
pushdown(l , r , x);
int mid = (l + r) >> 1;
ll ans = 0;
if(b <= mid) ans += query(b , e , lson);
if(e > mid) ans += query(b , e , rson);
return ans;
}
int main()
{
int n , m , opt , x , y;
ll z;
scanf("%d%d" , &n , &m);
build(1 , n , 1);
while(m -- )
{
scanf("%d%d%d" , &opt , &x , &y);
if(opt == 1) scanf("%lld" , &z) , update(x , y , z , 1 , n , 1);
else if(opt == 2) change(x , y , 1 , n , 1);
else printf("%lld\n" , query(x , y , 1 , n , 1));
}
return 0;
}
【uoj#228】基础数据结构练习题 线段树+均摊分析的更多相关文章
- UOJ #228. 基础数据结构练习题 线段树 + 均摊分析 + 神题
题目链接 一个数被开方 #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",st ...
- uoj #228. 基础数据结构练习题 线段树
#228. 基础数据结构练习题 统计 描述 提交 自定义测试 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的 ...
- uoj#228. 基础数据结构练习题(线段树区间开方)
题目链接:http://uoj.ac/problem/228 代码:(先开个坑在这个地方) #include<bits/stdc++.h> using namespace std; ; l ...
- 【loj6029】「雅礼集训 2017 Day1」市场 线段树+均摊分析
题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有四种:区间加.区间下取整除.区间求最小值.区间求和. $n\le 100000$ ,每次加的数在 $[-10^4,10^4]$ 之 ...
- 【线段树】uoj#228. 基础数据结构练习题
get到了标记永久化 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的好朋友九条可怜酱给她出了一道题. 给出一 ...
- 【UOJ#228】基础数据结构练习题 线段树
#228. 基础数据结构练习题 题目链接:http://uoj.ac/problem/228 Solution 这题由于有区间+操作,所以和花神还是不一样的. 花神那道题,我们可以考虑每个数最多开根几 ...
- uoj#228 基础数据结构练习题
题面:http://uoj.ac/problem/228 正解:线段树. 我们可以发现,开根号时一个区间中的数总是趋近相等.判断一个区间的数是否相等,只要判断最大值和最小值是否相等就行了.如果这个区间 ...
- bzoj4127 Abs 树链剖分+线段树+均摊分析
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4127 题解 首先区间绝对值和可以转化为 \(2\) 倍的区间正数和 \(-\) 区间和.于是问 ...
- uoj#228. 基础数据结构练习题(线段树)
传送门 只有区间加区间开方我都会--然而加在一起我就gg了-- 然后这题的做法就是对于区间加直接打标记,对于区间开方,如果这个区间的最大值等于最小值就直接区间覆盖(据ljh_2000大佬说这个区间覆盖 ...
随机推荐
- UWP 剪贴板 Clipboard
Clipboard使用Windows.ApplicationModel.DataTransfer.Clipboard 设置文本 DataPackage dataPackage = new DataPa ...
- h5小球走迷宫小游戏源码
无意中找到的一个挺有意思的小游戏,关键是用h5写的,下面就分享给大家源码 还是先来看小游戏的截图 可以用键盘的三个键去控制它,然后通关 下面是源代码 <!doctype html> < ...
- sqlmap注入分类
注入分法不同,种类不同,来个简单的分类: 1.get型:sqlmap -u “http://xxx.xx.xxx/xx.xxx?xx=xxx” 2.post型: sqlmap -u “http:// ...
- JMeter的__threadGroupName使用注意事项
JMeter从4.1版本开始引入了一个新函数"${__threadGroupName}",这个函数的作用是返回当前线程组的名字.${__threadGroupName}的用途也较为 ...
- GodMode | Windows上帝模式
最近在网上学习到了一些Windows的隐藏功能,今天我就来说说GodMode模式吧. 借鉴:https://jingyan.baidu.com/article/90bc8fc853c38bf65264 ...
- Netty源码分析第3章(客户端接入流程)---->第3节: NioSocketChannel的创建
Netty源码分析第三章: 客户端接入流程 第三节: NioSocketChannel的创建 回到上一小节的read()方法: public void read() { //必须是NioEventLo ...
- 如何通过阿里云APP进行域名备案?阿里云备案流程需要多久?
如何通过阿里云APP进行域名备案? 1.准备备案材料(很多初次使用阿里云APP进行备案的同学会问备案需要准备哪些资料,不二版本下面就给大家一一列举出来) 个人备案需要材料: ⑴<用户网站备案授权 ...
- dp算法之有代价的最短路径
题目:有代价的最短路径 题目介绍:如下图所示,现在平面上有N个点,此时N=7,每个点可能和其他点相连,相连的线有一定权值,求出从0点到N-1点的消耗权值的最小值. 分析:用动态规划的思路来解决,每一点 ...
- swapon和swapoff命令详解
基础命令学习目录首页 原文链接:https://blog.csdn.net/yexiangCSDN/article/details/83182259 swapon命令用于激活Linux系统中交换空间, ...
- 用python实现数字图片识别神经网络--启动网络的自我训练流程,展示网络数字图片识别效果
上一节,我们完成了网络训练代码的实现,还有一些问题需要做进一步的确认.网络的最终目标是,输入一张手写数字图片后,网络输出该图片对应的数字.由于网络需要从0到9一共十个数字中挑选出一个,于是我们的网络最 ...