UOJ228 简单数据结构练习题
Description
传送门
维护一个数列, 有以下操作:
对[l,r]同时加上x
把[l,r]开根后下取整.
查询[l,r]之和
n,m \(\leq\)$ 100000, $$a_i,x \leq 10^5$
Solution
考虑一个简易的线段树,直接对一个区间进行开根. 如果这个区间数字不同就继续往下递归. 因为 开根开不了多少次就会变成1,所以复杂度相对较小.但考虑一种情况:8 9 8 9 8 9 \(\dots\) 这样变成1后再区间修改变成原来的样子.然后就会TLE.
怎么办呢. 考虑一个小小优化,如果\(Max - \sqrt{Max} = Min - \sqrt{Min}\), 即区间变化量相同, 就直接转换为一个减法.
然后就跑过去了, 还跑得飞快.
分析一下复杂度:
对于一个数\(y =a^{2^{k}}\), 我们对他开根是:\(k\)次的, 即\(log_{2}({log_{a}(y)})\). 对于一个数, 我们在线段树上跳是\(log{n}\)次的.
我们定义势能V为相邻两数的差. 那么越开根号,V就越小.
显然,我们一次加法最多让V增加到最大值, 总势能为mV, 所以复杂度为\(O((n + m)logN * loglogV)\)
Codes
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define clar(a, b) memset((a), (b), sizeof(a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(s) debug("The massage in line %d, Function %s: %s\n", __LINE__, __FUNCTION__, s)
typedef long long LL;
typedef long double LD;
const int BUF_SIZE = (int)1e6 + 10;
struct fastIO {
char buf[BUF_SIZE], buf1[BUF_SIZE];
int cur, cur1;
FILE *in, *out;
fastIO() {
cur = BUF_SIZE, in = stdin, out = stdout;
cur1 = 0;
}
inline char getchar() {
if(cur == BUF_SIZE) fread(buf, BUF_SIZE, 1, in), cur = 0;
return *(buf + (cur++));
}
inline void putchar(char ch) {
*(buf1 + (cur1++)) = ch;
if (cur1 == BUF_SIZE) fwrite(buf1, BUF_SIZE, 1, out), cur1 = 0;
}
inline int flush() {
if (cur1 > 0) fwrite(buf1, cur1, 1, out);
return cur1 = 0;
}
}IO;
#define getchar IO.getchar
#define putchar IO.putchar
int read() {
char ch = getchar();
int x = 0, flag = 1;
for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
return x * flag;
}
void write(LL x) {
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar(x % 10 + 48);
}
void putString(char s[], char EndChar = '\n') {
rep(i, 0, strlen(s) - 1) putchar(*(s + i));
if(~EndChar) putchar(EndChar);
}
#define Maxn 100009
int n, m, a[Maxn];
namespace SGMT_tree {
LL Max[Maxn << 2], Min[Maxn << 2], sum[Maxn << 2], tag[Maxn << 2];
#define lc(x) ((x) << 1)
#define rc(x) (((x) << 1) | 1)
void pushup(int root) {
Max[root] = max(Max[lc(root)], Max[rc(root)]);
Min[root] = min(Min[lc(root)], Min[rc(root)]);
sum[root] = sum[lc(root)] + sum[rc(root)];
}
void pushdown(int root, int l, int r) {
LL v = tag[root];
if(v) {
int mid = (l + r) >> 1;
Max[lc(root)] += v, Min[lc(root)] += v, tag[lc(root)] += v; sum[lc(root)] += 1ll * v * (mid - l + 1);
Max[rc(root)] += v, Min[rc(root)] += v, tag[rc(root)] += v; sum[rc(root)] += 1ll * v * (r - mid);
tag[root] = 0;
}
}
void build(int root, int l, int r) {
if(l == r) {
Max[root] = Min[root] = sum[root] = a[l];
tag[root] = 0;
return ;
}
int mid = (l + r) >> 1;
build(lc(root), l, mid);
build(rc(root), mid + 1, r);
pushup(root);
}
void modify(int root, int l, int r, int x, int y, LL v) {
if(l > r || r < x || l > y) return ;
if(x <= l && r <= y) {
Max[root] += v, Min[root] += v, tag[root] += v;
sum[root] += 1ll * v * (1ll * r - l + 1);
return;
}
int mid = (l + r) >> 1;
pushdown(root, l, r);
modify(lc(root), l, mid, x, y, v);
modify(rc(root), mid + 1, r, x, y, v);
pushup(root);
}
void modify(int root, int l, int r, int x, int y) {
if(l > r || r < x || l > y) return ;
if(x <= l && r <= y) {
if(Max[root] - ((int)sqrt(Max[root])) == Min[root] - ((int)sqrt(Min[root]))) {
LL v = -Max[root] + ((int)sqrt(Max[root]));
Max[root] += v, Min[root] += v, tag[root] += v, sum[root] += 1ll * v * (r - l + 1);
return ;
}
}
int mid = (l + r) >> 1;
pushdown(root, l, r);
modify(lc(root), l, mid, x, y);
modify(rc(root), mid + 1, r, x, y);
pushup(root);
}
LL query(int root, int l, int r, int x, int y) {
if(l > r || r < x || l > y) return 0;
if(x <= l && r <= y) return sum[root];
int mid = (l + r) >> 1; LL res = 0;
pushdown(root, l, r);
res += query(lc(root), l, mid, x, y);
res += query(rc(root), mid + 1, r, x, y);
pushup(root);
return res;
}
}
namespace INIT {
void Main() {
n = read(); m = read();
rep(i, 1, n) a[i] = read();
SGMT_tree :: build(1, 1, n);
}
}
namespace SOLVE {
void Main() {
rep(i, 1, m) {
int opt = read();
if(opt == 1) {
int l = read(), r = read(), x = read();
SGMT_tree :: modify(1, 1, n, l, r, x);
}
if(opt == 2) {
int l = read(), r = read();
SGMT_tree :: modify(1, 1, n, l, r);
}
if(opt == 3) {
int l = read(), r = read();
write(SGMT_tree :: query(1, 1, n, l, r)), putchar('\n');
}
}
}
}
int main() {
#ifdef Qrsikno
freopen("uoj228.in", "r", stdin);
freopen("uoj228.out", "w", stdout);
#endif
INIT :: Main();
SOLVE :: Main();
#ifdef Qrsikno
debug("\nRunning time: %.3lf(s)\n", clock() * 1.0 / CLOCKS_PER_SEC);
#endif
return IO.flush();
}
UOJ228 简单数据结构练习题的更多相关文章
- uoj228 基础数据结构练习题
趁别人题解没有放出来赶快写一篇 整数序列,操作 区间加 区间变成sqrt(下取整) 区间和 考虑一下对于每个区间里所有sqrt不同的段操作,那么可以在O(段数logn)一次的时间内完成sqrt操作.考 ...
- [UOJ228] 基础数据结构练习题 - 线段树
考虑到一个数开根号 \(loglog\) 次后就会变成1,设某个Node的势能为 \(loglog(maxv-minv)\) ,那么一次根号操作会使得势能下降 \(1\) ,一次加操作最多增加 \(l ...
- 【UOJ228】基础数据结构练习题(线段树)
[UOJ228]基础数据结构练习题(线段树) 题面 UOJ 题解 我们来看看怎么开根? 如果区间所有值都相等怎么办? 显然可以直接开根 如果\(max-sqrt(max)=min-sqrt(min)\ ...
- 【UOJ#228】基础数据结构练习题 线段树
#228. 基础数据结构练习题 题目链接:http://uoj.ac/problem/228 Solution 这题由于有区间+操作,所以和花神还是不一样的. 花神那道题,我们可以考虑每个数最多开根几 ...
- uoj #228. 基础数据结构练习题 线段树
#228. 基础数据结构练习题 统计 描述 提交 自定义测试 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的 ...
- python学习总结----简单数据结构
mini-web服务器 - 能够完成简单的请求处理 - 使用http协议 - 目的:加深对网络编程的认识.为后面阶段学习web做铺垫 简单数据结构 - 排列组合 import itertools # ...
- 牛客练习赛22-E.简单数据结构1(扩展欧拉定理降幂 +树状数组)
链接:E.简单数据结构1 题意: 给一个长为n的序列,m次操作,每次操作: 1.区间加 2.对于区间,查询 ,一直到- 请注意每次的模数不同. 题解:扩展欧拉定理降幂 对一个数p取log(p)次的 ...
- [LOJ#2326]「清华集训 2017」简单数据结构
[LOJ#2326]「清华集训 2017」简单数据结构 试题描述 参加完IOI2018之后就是姚班面试.而你,由于讨厌物理.并且想成为乔布斯一样的创业家,被成功踢回贵系. 转眼,时间的指针被指向201 ...
- 简单数据结构题(from 钟子谦——IOI2018集训队自选题)
简单数据结构题(from 钟子谦--IOI2018集训队自选题) 试题描述 给一棵 \(n\) 个点的树,点权开始为 \(0\) ,有 \(q\) 次操作,每次操作是选择一个点,把周围一圈点点权 \( ...
随机推荐
- C语言必会面试题(3、耶稣有13个门徒,当中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:13人围坐一圈,从第一个開始报号:1,2,3,1,2,3...。凡是报到“3”就退出圈子,...)
3.耶稣有13个门徒.当中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:13人围坐一圈,从第一个開始报号:1.2,3.1,2,3.... 凡是报到"3"就退出圈子.最后留在圈子 ...
- 3.将maven项目jar纳入maven仓库,Mave项目依赖另外一个Maven项目的案例
1 若想让maven项目依赖另外一个maven项目.被依赖的项目要在maven仓库中有对应的jar包,所以要对依赖的项目运行mvninstall命令. 2 新建第二个项目模块HelloFrien ...
- 通过SQL SERVER加入系统管理员帐号
通过SQL SERVER加入系统管理员帐号.当然是须要有足够的权限,远程链接数据库后执行脚本,脚本例如以下: /* 此代码是在master数据库下执行 添加系统管理员:mmcgzs password: ...
- java的自动类型转换
package BaseType; /*java的自动类型提升和窄化转换 * * 1. 当一个char,short,byte类型的变量被赋值给一个超出他自身能表示的最大范围的数,java会自动将该数转 ...
- 给GridView设置行高
近期在工作中遇到了这样一个问题,使用一个GridView展示数据,item中仅仅是一个TextView,可是里面显示的文字多少不固定多少,必须所有展示出来. 遇到的问题: 1.把item中的宽和高设置 ...
- windows下使用mingw和msys编译GOTOBLAS和OpenBLAS
在windows下利用msys编译openBLAS若遇到错误提示: gcc: CreateProcess : No such file or directory 问题原因参考:http://www.c ...
- 2016/2/24 css画三角形 border的上右下左的调整 以及内区域的无限变小 边界透明
网页因为 CSS 而呈现千变万化的风格.这一看似简单的样式语言在使用中非常灵活,只要你发挥创意就能实现很多比人想象不到的效果.特别是随着 CSS3 的广泛使用,更多新奇的 CSS 作品涌现出来. 今天 ...
- 51NOD 1821 最优集合 栈
1821 最优集合 一个集合S的优美值定义为:最大的x,满足对于任意i∈[1,x],都存在一个S的子集S',使得S'中元素之和为i. 给定n个集合,对于每一次询问,指定一个集合S1和一个集合S2, ...
- 使用spring框架时,使用xml还是注解
1 xml的优缺点 1.1 优点 解耦合,方便维护.xml不入侵代码,方便代码阅读. 1.2 缺点 开发速度慢. 2 注解的优缺点 2.1 优点 能够加快开发速度,因为它将常用的主体逻辑隐藏在注解中了 ...
- 前端富文本 js 版本
https://s3.pstatp.com/pgc/v2/resource/tt_ueditor_v3_temple/tt-editor.all.js?20180425