题目描述

You are given a sequence \(A\) of \(N(N \leq 100,000)\) positive integers. There sum will be less than \(10^{18}\) . On this sequence you have to apply \(M (M \leq 100,000)\) operations:

(A) For given \(x\),\(y\), for each elements between the \(x-th\) and the \(y-th\) ones (inclusively, counting from \(1\)), modify it to its positive square root (rounded down to the nearest integer).

(B) For given \(x\),\(y\), query the sum of all the elements between the \(x-th\) and the \(y-th\) ones (inclusively, counting from \(1\)) in the sequence.

输入输出格式

输入格式

Multiple test cases, please proceed them one by one. Input terminates by \(EOF\).

For each test case:

The first line contains an integer \(N\). The following line contains \(N\) integers, representing the sequence \(A_{1}..A_{N}\).

The third line contains an integer \(M\). The next \(M\) lines contain the operations in the form i x y.

\(i=0\) denotes the modify operation, \(i=1\) denotes the query operation.

输出格式

For each test case:

Output the case number (counting from \(1\)) in the first line of output. Then for each query, print an integer as the problem required.

Print an blank line after each test case.

See the sample output for more details.

输入输出样例

输入样例#1

5
1 2 3 4 5
5
1 2 4
0 2 4
1 2 4
0 4 5
1 1 5
4
10 10 10 10
3
1 1 4
0 2 3
1 1 4

输出样例#1

Case #1:
9
4
6 Case #2:
40
26

题意翻译

「题意」: \(n\) 个数,和在\(10^{18}\) 范围内。

也就是\(\sum~a_i~\leq~10^{18}\)

现在有「两种」操作

0 x y把区间\([x,y]\) 内的每个数开方,下取整

1 x y询问区间\([x,y]\) 的每个数的和

「格式」: 有多组数据,数据以\(EOF\)结束,对于每组数据,输出数据的序号,每组数据之后输出一个空行。

「注意」: 不保证给出的区间\([x, y]\) 有\(x <= y\) ,如果\(x>y\) 请交换\(x\) ,\(y\)。

题解

\(SPOJ\)的\(GSS\)系列第四题。

乍一看和这题一模一样,于是准备直接拿一样的代码提交。

猛然发现:数据范围差了那么远!

这题中\(0 \leq n \leq 50000\),\(-2^{31} \leq others\)、\(ans \leq 2^{31} - 1\)。

而本题中\(n \leq 100000\),\(\sum~a_i~\leq~10^{18}\)直接提交一样的代码肯定会\(TLE\)。

于是尝试线段树。

普通操作与线段树大同小异,只是需要注意一个点:一个数已经小于或等于1就不要再开方了!

为什么呢?因为大于\(1\)的数开方会越来越接近\(1\),而小于\(1\)的数开方也会越来越接近\(1\),又因为\(\sqrt{1} = 1\),因此任何数经过开方操作都可以到\(1\)。

不难得出\(AC\)代码。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype> using namespace std; inline int gi()//快速读入
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar();}
return f * x;
} const int maxn = 100000 + 5;
int n, m, Case;
long long tr[maxn << 2], a[maxn], sq[maxn << 2];//tr为区间和,a为数字序列,sq为区间最大值 inline void pushup(int p)//上传节点
{
tr[p] = tr[p << 1] + tr[(p << 1) | 1];//增加区间和
sq[p] = max(sq[p << 1], sq[(p << 1) | 1]);//计算最大值
} void build(int s, int t, int p)//建树
{
if (s == t)//已经是叶子节点
{
tr[p] = sq[p] = a[s];//初始化节点信息
return;//直接返回
}
int mid = (s + t) >> 1;//计算中点
build(s, mid, p << 1);//递归左子树
build(mid + 1, t, (p << 1) | 1);//递归右子树
pushup(p);//上传当前节点
} void modify(int l, int r, int s, int t, int p)//进行区间开方操作
{
if (s == t)//已经到了叶子节点
{
tr[p] = sqrt(tr[p]);//进行开方
sq[p] = tr[p];//区间最大值就是当前数
return;//返回
}
int mid = (s + t) >> 1;//计算中间值
if (l <= mid && sq[p << 1] > 1) //如果目标节点在左区间且左区间最大值大于1
modify(l, r, s, mid, p << 1);//就递归左子树寻找目标节点
if (r > mid && sq[(p << 1) | 1] > 1) //目标节点在右区间且右区间最大值大于1
modify(l, r, mid + 1, t, (p << 1) | 1);//递归右子树寻找目标节点
pushup(p);//上传当前节点
} long long getans(int l, int r, int s, int t, int p)//寻找答案
{
if (l <= s && r >= t)//当前区间包含于目标区间
{
return tr[p];//直接返回当前区间信息
}
long long sum = 0;//要返回的和
int mid = (s + t) >> 1;//计算中间值
if (l <= mid)//如果左端点在中点左侧
{
sum = sum + getans(l, r, s, mid, p << 1);//加上左区间的答案
}
if (r > mid)//如果右端点在中点右侧
{
sum = sum + getans(l, r, mid + 1, t, (p << 1) | 1);//加上右区间的答案
}
return sum;//返回答案
} int main()
{
while (~scanf("%d", &n))//多组数据
{
printf("Case #%d:\n", ++Case);
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
memset(tr, 0, sizeof(tr));
memset(sq, 0, sizeof(sq));//多组数据要初始化
build(1, n, 1);//建树
m = gi();//输入询问个数
for (int i = 1; i <= m; i++)
{
int x = gi(), y = gi(), z = gi();
if (y > z) swap(y, z);//如果左端点大于右端点,就交换它们
if (x == 1)//是询问区间和
{
printf("%lld\n", getans(y, z, 1, n, 1));//输出答案
}
else
{
modify(y, z, 1, n, 1);//否则就进行区间开方
}
}
puts("");//一定记得数据之间要空行
}
return 0;//结束
}

题解【SP2713】GSS4 - Can you answer these queries IV的更多相关文章

  1. 线段树 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 ...

  2. SP2713 GSS4 - Can you answer these queries IV(线段树)

    传送门 解题思路 大概就是一个数很少次数的开方会开到\(1\),而\(1\)开方还是\(1\),所以维护一个和,维护一个开方标记,维护一个区间是否全部为\(1/0\)的标记.然后每次修改时先看是否有全 ...

  3. 【SP2713 GSS4 - Can you answer these queries IV】 题解

    题目链接:https://www.luogu.org/problemnew/show/SP2713 真暴力啊. 开方你开就是了,开上6次就都没了. #include <cmath> #in ...

  4. SP2713 GSS4 - Can you answer these queries IV

    题目大意 \(n\) 个数,和在\(10^{18}\)范围内. 也就是\(\sum~a_i~\leq~10^{18}\) 现在有两种操作 0 x y 把区间[x,y]内的每个数开方,下取整 1 x y ...

  5. SP2713 GSS4 - Can you answer these queries IV 分块

    问题描述 LG-SP2713 题解 分块,区间开根. 如果一块的最大值是 \(1\) ,那么这个块就不用开根了. 如果最大值不是 \(1\) ,直接暴力开就好了. \(\mathrm{Code}\) ...

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

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

  7. GSS4 - Can you answer these queries IV(线段树懒操作)

    GSS4 - Can you answer these queries IV(线段树懒操作) 标签: 线段树 题目链接 Description recursion有一个正整数序列a[n].现在recu ...

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

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

  9. 题解 SP2713 【GSS4 - Can you answer these queries IV】

    用计算器算一算,就可以发现\(10^{18}\)的数,被开方\(6\)次后就变为了\(1\). 所以我们可以直接暴力的进行区间修改,若这个数已经到达\(1\),则以后就不再修改(因为\(1\)开方后还 ...

随机推荐

  1. 纪中5日T3 1566. 幸运锁(lucky.pas/c/cpp)

    1566. 幸运锁(lucky.pas/c/cpp) 题目描述 有一把幸运锁,打开它将会给你带来好运,但开锁时需要输入一个正整数(没有前导0).幸运锁有一种运算,对于一个正整数,返回他的相邻两位数字间 ...

  2. mac anyconnect 卸载方法

    打开终端: 输入下面的命令 sudo /opt/cisco/vpn/bin/vpn_uninstall.sh 有问题 端口占用 sudo /opt/cisco/anyconnect/bin/webse ...

  3. Educational Codeforces Round 46 (Rated for Div. 2) D

    dp[i]表示一定包含第I个点的好的子序列个数,那么最终答案就是求dp[0] + dp[1] + .... + dp[n-1] 最终的子序列被分成了很多块,因此很明显我们枚举第一块,第一块和剩下的再去 ...

  4. CentOS 7 部署 Redis(单机版)

    一.部署环境说明 软件 版本 安装包 CentOS 7.2 CentOS 7.2 Redis 4.0.14 redis-4.0.14.tar.gz 二.开始部署 安装gcc依赖 [root@bmsof ...

  5. python三器

    1.1 装饰器 1.装饰器的作用 1. 装饰器作用:本质是函数(装饰其他函数)就是为其他函数添加其他功能 2. 装饰器必须准寻得原则: 1)不能修改被装饰函数的源代码 2)不能修改被装饰函数的调用方式 ...

  6. 7-5 A除以B(10 分)

    真的是简单题哈 —— 给定两个绝对值不超过100的整数A和B,要求你按照“A/B=商”的格式输出结果. 输入格式:输入在第一行给出两个整数A和B(−100≤A,B≤100),数字间以空格分隔. 输出格 ...

  7. 《Python学习手册 第五版》 -第14章 迭代和推导

    承接上一章for循环的讲解,迭代和推导,是对for循环的一种深入的探索和扩展 本章重点内容 1.迭代 1)什么是迭代?都有哪些分类 2)常规的使用方法 3)多遍迭代器VS单遍迭代器 2.列表推导 1) ...

  8. MyEclipse CI 2019.4 完美激活版(含离线包+激活工具+安装教程)

    ps:MyEclipse目前已更新至2019.12.5,但是目前还没有有效的激活方式,本次文章以2019.4为例; 该文章使用离线安装的方式进行安装,在线安装不保证不会出现各类小问题,离线安装包及激活 ...

  9. 数据预处理 | 使用 OneHotEncoder 及 get_dummuies 将分类型数据转变成哑变量矩阵

    [分类数据的处理] 问题: 在数据建模过程中,很多算法或算法实现包无法直接处理非数值型的变量,如 KMeans 算法基于距离的相似度计算,而字符串则无法直接计算距离 如: 性别中的男和女 [0,1] ...

  10. 机器学习笔记(十一)OCR技术的应用

    1.介绍OCR: OCR(Photo optical character recognition 照片光学字符识别) 应用于读取电子照片中的文字. 2.算法思路: ① 识别文字区域: ② 字符切分: ...