题目描述

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. H5 meta标签常用写法

    <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content=" ...

  2. zedboard通过BRAM实现PS和PL的简单通信

    使用Block Memory进行PS和PL的数据交互或者数据共享,通过zynq PS端的Master GP0端口向BRAM写数据,然后再通过PS端的Mater GP1把数据读出来,将结果打印输出到串口 ...

  3. 虚拟化技术xen的简介和安装

    虚拟化技术的分类: 1,模拟:Emulation ​ Qemu,PearPC,Bochs 2,完全虚拟化:Full Virtualization,Native Virtualization ​ HVM ...

  4. springboot里面的缓存注解

    https://blog.csdn.net/u012240455/article/details/80844361 https://lfvepclr.gitbooks.io/spring-framew ...

  5. 曼孚科技:AI自然语言处理(NLP)领域常用的16个术语

    ​自然语言处理(NLP)是人工智能领域一个十分重要的研究方向.NLP研究的是实现人与计算机之间用自然语言进行有效沟通的各种理论与方法. 本文整理了NLP领域常用的16个术语,希望可以帮助大家更好地理解 ...

  6. openWRT和LuCI

    openwrt是一套集成在板子上的系统,通过ip进入到其页面上 Luci是lua和UCI统一配置接口的合体,实现路由的网页配置界面(相当于一个前端框架)

  7. PP: Multi-Horizon Time Series Forecasting with Temporal Attention Learning

    Problem: multi-horizon probabilistic forecasting tasks; Propose an end-to-end framework for multi-ho ...

  8. php Allowed memory size of 134217728 bytes exhausted

    报错:PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 72 bytes) in ...

  9. 《JavaScript ES6 函数式编程入门经典》--推荐指数⭐⭐⭐

    这本书比较基础认真看完再自己写点demo一个双休日就差不多, 总体来说看完还是有收获的,会激起一些你对函数编程的兴趣 主要目录如下: 第1章 函数式编程简介 11.1 什么是函数式编程?为何它重要 1 ...

  10. 一起学Vue之列表渲染

    在Vue开发中,列表数据绑定非常简单易用,本文主要通过一些简单的小例子,讲述v-for的使用方法,仅供学习分享使用,如有不足之处,还请指正. 用 v-for 把一个数组对应为一组元素 我们可以用 v- ...