题目链接


题解

题目大意

一个序列,支持区间开方与求和操作。

算法:线段树实现开方修改与区间求和

分析

  • 显然,这道题的求和操作可以用线段树来维护
  • 但是如何来实现区间开方呢
  • 大家有没有这样的经历:玩计算器的时候,把一个数疯狂的按开方,最后总会变成 \(1\),之后在怎样开方也是 \(1\) (\(\sqrt1=1\))
  • 同样的,\(\sqrt0=0\)
  • 所以,只要一段区间里的所有数全都 \(\leq 1\) 了,便可以不去修改它

实现

  • 线段树维护区间和 \(sum\) 与最大值 \(Max\)
  • 在修改过程中,只去修改 \(Max > 1\) 的区间
  • 到了叶子节点对\(sum\)和\(Max\)进行开方就行了

复杂度

  • 每个数 \(\leq 10 ^ {12}\),所以至多开方\(6\)次便可以得到\(1\)
  • 每次操作是 \(\log n\)的,总复杂度\(O(n \log n)\)

注意事项

  • 请使用long long
  • 可能 \(l > r\)(把我坑了)

代码:

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstdio> using namespace std;
typedef long long LL;
const int MAXN = 100100; int n, m;
int cnt;
LL a[MAXN];
struct node
{
int left, right;
LL s, Max;
node *ch[2];
}pool[MAXN << 2], *root; inline void pushup(node *r)
{
r->s = r->ch[0]->s + r->ch[1]->s;
r->Max = max(r->ch[0]->Max, r->ch[1]->Max);
} inline void Build_Tree(node *r, int left, int right)
{
r->left = left;
r->right = right;
if(left == right)
{
r->s = r->Max = a[left];
return ;
}
int mid = (left + right) / 2;
node *lson = &pool[++cnt];
node *rson = &pool[++cnt];
r->ch[0] = lson;
r->ch[1] = rson;
Build_Tree(lson, left, mid);
Build_Tree(rson, mid + 1, right);
pushup(r);
} inline void change(node *r, int left, int right)
{
if(r->left == r->right)
{
r->s = sqrt(r->s);
r->Max = sqrt(r->Max);
return ;
} int mid = (r->left +r-> right) / 2;
if(left <= mid && r->ch[0]->Max > 1) change(r->ch[0], left, right);
if(mid < right && r->ch[1]->Max > 1) change(r->ch[1], left, right);
pushup(r);
} inline LL query(node *r, int left, int right)
{
if(r->left == left && r->right == right)
return r->s;
if(r->ch[0]->right >= right) return query(r->ch[0], left, right);
else if(r->ch[1]->left <= left) return query(r->ch[1], left, right);
else
return query(r->ch[0], left, r->ch[0]->right) +
query(r->ch[1], r->ch[1]->left, right);
}
int main()
{
scanf("%d", &n);
root = &pool[0];
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
scanf("%d", &m);
Build_Tree(root, 1, n);
for(int i = 1; i <= m; i++)
{
int opt, l, r;
scanf("%d%d%d", &opt, &l, &r);
if(l > r) swap(l, r);
if(opt) printf("%lld\n", query(root, l, r));
else change(root, l, r);
}
return 0;
}

题解【luoguP4145 上帝造题的七分钟2(花神游历各国)】的更多相关文章

  1. 题解 洛谷 P4145 【上帝造题的七分钟2 / 花神游历各国】

    题目 上帝造题的七分钟2 / 花神游历各国 题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. ...

  2. GSS4 - Can you answer these queries IV || luogu4145上帝造题的七分钟2 / 花神游历各国 (线段树)

    GSS4 - Can you answer these queries IV || luogu4145上帝造题的七分钟2 / 花神游历各国 GSS4 - Can you answer these qu ...

  3. 洛谷P4145 上帝造题的七分钟2 / 花神游历各国(重题:洛谷SP2713 GSS4 - Can you answer these queries IV)

    题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段 ...

  4. 洛谷P4145 上帝造题的七分钟2/花神游历各国 [树状数组,并查集]

    题目传送门 题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是 ...

  5. [bzoj3038/3211]上帝造题的七分钟2/花神游历各国_线段树

    上帝造题的七分钟2 bzoj-3038 题目大意:给定一个序列,支持:区间开方:查询区间和. 注释:$1\le n\le 10^5$,$1\le val[i] \le 10^{12}$. 想法:这题还 ...

  6. 洛谷P4145——上帝造题的七分钟2 / 花神游历各国

    题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段 ...

  7. 【luogu4145】上帝造题的七分钟2 / 花神游历各国--区间开根-线段树

    题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段 ...

  8. 【题解】 Luogu P4145 上帝造题的七分钟2 / 花神游历各国

    原题传送门 这道题实际和GSS4是一样的,只是输入方式有点区别 GSS4传送门 这道题暴力就能过qaq(这里暴力指线段树) 数据比较水 开方修改在线段树中枚举叶节点sqrt 查询区间和线段树基本操作 ...

  9. 线段树 SP2713 GSS4 - Can you answer these queries IV暨 【洛谷P4145】 上帝造题的七分钟2 / 花神游历各国

    SP2713 GSS4 - Can you answer these queries IV 「题意」: n 个数,每个数在\(10^{18}\) 范围内. 现在有「两种」操作 0 x y把区间\([x ...

  10. 洛谷 P4145 上帝造题的七分钟2 / 花神游历各国

    洛谷 这题就是区间开根号,区间求和.我们可以分块做. 我们记布尔数组vis[i]表示第i块中元素是否全部为1. 因为显然当一个块中元素全部为1时,并不需要对它进行根号操作. 我们每个块暴力开根号,因为 ...

随机推荐

  1. py3.6+anaconda下安装opencv3

    py3.6+anaconda下安装opencv3 首先声明-网上的方法大多数都是有毒的.也不知道给的什么鬼方法都不行. 我说下我的方法.去这个网站https://pypi.tuna.tsinghua. ...

  2. Microservices with Spring Boot

    找到一套比较不错的Spring Boot/Cloud入门教程,推荐一下. https://dzone.com/users/1041459/ranga_pec.html

  3. 自测之Lesson15:TCP&UDP网络编程

    题目:编写一个TCP通信的程序. 实现代码: #include <stdio.h> #include <sys/socket.h> #include <unistd.h& ...

  4. Android游戏音效实现

    1. 游戏音效SoundPool 游戏中会根据不同的动作 , 产生各种音效 , 这些音效的特点是短暂(叫声,爆炸声可能持续不到一秒) , 重复(一个文件不断重复播放) , 并且同时播放(比如打怪时怪的 ...

  5. ajax 返回值问题

    错误示例:function returnFlag(){ $.ajax({ type:"post", dataType:"json", data:JSON.str ...

  6. lintcode-16-带重复元素的排列

    带重复元素的排列 给出一个具有重复数字的列表,找出列表所有不同的排列. #### 样例 给出列表 [1,2,2],不同的排列有: [ [1,2,2], [2,1,2], [2,2,1] ] 挑战 使用 ...

  7. position定位-absolute与fixed

    1. absolute 生成绝对定位元素,相对于static定位以外的第一个父元素进行定位. 2. fixed 生成绝对定位元素,相对于浏览器窗口进行定位.

  8. Sass的命令编译

    [Sass]命令编译 命令编译是指使用你电脑中的命令终端,通过输入 Sass 指令来编译 Sass.这种编译方式是最直接也是最简单的一种方式.因为只需要在你的命令终端输入: 单文件编译: sass & ...

  9. UML图之协作图

    创建方法: 1,new----collaboration diagram 2,根据序列图按F5转换 增加对象链接(图2-4-4)    (1) 选择Object Link 工具栏按钮. (2) 单击要 ...

  10. JAVA学习之泛型

    ArrayList<E>类定义和ArrayList<Integer>类引用中涉及的术语:1.整个ArrayList<E>称为泛型类型 2.ArrayList< ...