题意

给出一些数,有两种操作。(1)将区间内每一个数开方(2)查询每一段区间的和

分析

普通的线段树保留修改+开方优化。可以知道当一个数为0或1时,无论开方几次,答案仍然相同。所以设置flag=1变表示这一段区间全是0/1,那么修改的时候直接暴力遍历线段树结点。因为一个数被开方下取整到1,只会被开方几次,所以说这样修改是O(n)O(n)O(n)的.总时间还是O(nlogn)O(nlogn)O(nlogn)

CODE1

上帝造题的七分钟2

#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; int flg = 1; for(;!isdigit(ch=getc());)if(ch=='-')flg=-flg;
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 100005;
int n, m;
struct seg {
LL sum; bool flg;
}t[MAXN<<2];
inline void upd(int i) {
t[i].sum = t[i<<1].sum + t[i<<1|1].sum;
t[i].flg = t[i<<1].flg & t[i<<1|1].flg;
}
void build(int i, int l, int r) {
t[i].flg = 0;
if(l == r) {
read(t[i].sum);
if(t[i].sum <= 1) t[i].flg = 1;
return;
}
int mid = (l + r) >> 1;
build(i<<1, l, mid);
build(i<<1|1, mid+1, r);
upd(i);
}
void modify(int i, int l, int r, int x, int y) {
if(t[i].flg) return;
if(l == r) {
t[i].sum = sqrt(t[i].sum);
if(t[i].sum <= 1) t[i].flg = 1;
return;
}
int mid = (l + r) >> 1;
if(x <= mid) modify(i<<1, l, mid, x, y);
if(y > mid) modify(i<<1|1, mid+1, r, x, y);
upd(i);
}
LL query(int i, int l, int r, int x, int y) {
if(x <= l && r <= y) return t[i].sum;
int mid = (l + r) >> 1;
if(y <= mid) return query(i<<1, l, mid, x, y);
else if(x > mid) return query(i<<1|1, mid+1, r, x, y);
else return query(i<<1, l, mid, x, y) + query(i<<1|1, mid+1, r, x, y);
}
int main () {
read(n); build(1, 1, n); read(m);
int x, y, op;
while(m--) {
read(op), read(x), read(y);
if(x > y) swap(x, y); //坑!
if(!op) modify(1, 1, n, x, y);
else printf("%lld\n", query(1, 1, n, x, y));
}
}

CODE 2

花神游历各国

#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; int flg = 1; for(;!isdigit(ch=getc());)if(ch=='-')flg=-flg;
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 100005;
int n, m;
struct seg {
LL sum; bool flg;
}t[MAXN<<2];
inline void upd(int i) {
t[i].sum = t[i<<1].sum + t[i<<1|1].sum;
t[i].flg = t[i<<1].flg & t[i<<1|1].flg;
}
void build(int i, int l, int r) {
t[i].flg = 0;
if(l == r) {
read(t[i].sum);
if(t[i].sum <= 1) t[i].flg = 1;
return;
}
int mid = (l + r) >> 1;
build(i<<1, l, mid);
build(i<<1|1, mid+1, r);
upd(i);
}
void modify(int i, int l, int r, int x, int y) {
if(t[i].flg) return;
if(l == r) {
t[i].sum = sqrt(t[i].sum);
if(t[i].sum <= 1) t[i].flg = 1;
return;
}
int mid = (l + r) >> 1;
if(x <= mid) modify(i<<1, l, mid, x, y);
if(y > mid) modify(i<<1|1, mid+1, r, x, y);
upd(i);
}
LL query(int i, int l, int r, int x, int y) {
if(x <= l && r <= y) return t[i].sum;
int mid = (l + r) >> 1;
if(y <= mid) return query(i<<1, l, mid, x, y);
else if(x > mid) return query(i<<1|1, mid+1, r, x, y);
else return query(i<<1, l, mid, x, y) + query(i<<1|1, mid+1, r, x, y);
}
int main () {
read(n); build(1, 1, n); read(m);
int x, y, op;
while(m--) {
read(op), read(x), read(y);
if(op == 2) modify(1, 1, n, x, y);
else printf("%lld\n", query(1, 1, n, x, y));
}
}

BZOJ 3038: 上帝造题的七分钟2 / BZOJ 3211: 花神游历各国 (线段树区间开平方)的更多相关文章

  1. BZOJ 3038: 上帝造题的七分钟2

    3038: 上帝造题的七分钟2 Description XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分 ...

  2. BZOJ 3038: 上帝造题的七分钟2【线段树区间开方问题】

    3038: 上帝造题的七分钟2 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1469  Solved: 631[Submit][Status][Dis ...

  3. bzoj 3038: 上帝造题的七分钟2 线段树||hdu 4027

    3038: 上帝造题的七分钟2 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1066  Solved: 476[Submit][Status][Dis ...

  4. BZOJ 3038 上帝造题的七分钟2 (并查集+树状数组)

    题解:同 BZOJ 3211 花神游历各国,需要注意的是需要开long long,还有左右节点需要注意一下. #include <cstdio> #include <cmath> ...

  5. BZOJ 3038 上帝造题的七分钟2 树状数组+并查集

    题目大意:一个序列,有两种操作.1.将一段数中的每个数开根号.2.查询一段数的和. 思路:和3211是一个题,有兴趣的能够看看我的那篇博客. CODE: #include <cmath> ...

  6. BZOJ 3038 上帝造题的七分钟二

    无题目 但是百度会发现题目和3211基本一致 所以看上一篇博文的上一篇博文呢

  7. BZOJ 3211: 花神游历各国( 线段树 )

    线段树...区间开方...明显是要处理到叶节点的 之前在CF做过道区间取模...差不多, 只有开方, 那么每个数开方次数也是有限的(0,1时就会停止), 最大的数10^9开方10+次也就不会动了.那么 ...

  8. BZOJ 3211 花神游历各国 线段树平方开根

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3211 题目大意: 思路: 由于数据范围只有1e9,一个数字x开根号次数超过logx之后 ...

  9. 【BZOJ】3038: 上帝造题的七分钟2(线段树+暴力)

    http://www.lydsy.com:808/JudgeOnline/problem.php?id=3038 这题我就有得吐槽了,先是线段树更新写错,然后不知哪没pushup导致te,精度问题sq ...

随机推荐

  1. poj3449(判断直线相交)

    题目链接:https://vjudge.net/problem/POJ-3449 题意:给出若干几何体,判断每个几何体与其它几何体的相交情况,并依次输出. 思路: 首先要知道的是根据正方形对角线的两个 ...

  2. JS利用async、await处理少见的登录业务逻辑

    在用uniapp开发一个项目时,有这样一个需求:用户首次登录后,uniapp自动保存用户名密码,之后不管是再次打开项目(打开项目时登录状态已失效)还是 请求接口(接口返回登录失效)时,都会先自动默认的 ...

  3. Python解Leetcode: 539. Minimum Time Difference

    题目描述:给定一个由时间字符组成的列表,找出任意两个时间之间最小的差值. 思路: 把给定的链表排序,并且在排序的同时把60进制的时间转化成十进制整数: 遍历排序的数组,求出两个相邻值之间的差值: 求出 ...

  4. Java实现无向图的建立与遍历

    一.基于邻接矩阵表示法的无向图 邻接矩阵是一种利用一维数组记录点集信息.二维数组记录边集信息来表示图的表示法,因此我们可以将图抽象成一个类,点集信息和边集信息抽象成类的属性,就可以在Java中描述出来 ...

  5. Django-djangorestframework-异常模块-源码及自定义异常

    目录 异常模块 为什么要自定义异常模块 常见的几种异常情况 异常模块源码分析 自定义 drf 异常处理 异常模块 为什么要自定义异常模块 所有经过 drf APIView 视图类产生的异常,都可以提供 ...

  6. 第十二章 ZYNQ-MIZ702 PS读写PL端BRAM

      本篇文章目的是使用Block Memory进行PS和PL的数据交互或者数据共享,通过zynq PS端的Master GP0端口向BRAM写数据,然后再通过PS端的Mater GP1把数据读出来,将 ...

  7. Java 抽象类详解

    在<Java中的抽象方法和接口>中,介绍了抽象方法与接口,以及做了简单的比较. 这里我想详细探讨下抽象类. 一.抽象类的定义 被关键字“abstract”修饰的类,为抽象类.(而且,abx ...

  8. java都13了, 8的新特性你还没不会用吗

    前言 java13都已经来了,很多同学还停留在使用java5的东西.如果在日常开发中没有使用上java8的一些新特性或者不会用.这篇文章对你可能有帮助. lambda表达式 介绍 lambda表达式是 ...

  9. windows下安装mongoDB(zip版)

    windows下安装mongoDB(zip版) 下面说明如何在win10下用zip包安装好mongoDB数据库 首先要先从网上下载mongoDB的zip包 http://dl.mongodb.org/ ...

  10. javaIO——LineNumberReader

    LineNumberReader 是java字符流中的一员,它继承自 BufferedReader,只是在 BufferedReader 基础上,提供了对当前流位置所在文本行的标记记录.先来看看定义: ...