HDU-Can you answer these queries? (线段树+区间修改)

Problem Description

A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use our secret weapon to eliminate the battleships. Each of the battleships can be marked a value of endurance. For every attack of our secret weapon, it could decrease the endurance of a consecutive part of battleships by make their endurance to the square root of it original value of endurance. During the series of attack of our secret weapon, the commander wants to evaluate the effect of the weapon, so he asks you for help.
You are asked to answer the queries that the sum of the endurance of a consecutive part of the battleship line.

Notice that the square root operation should be rounded down to integer.

Input

The input contains several test cases, terminated by EOF.
  For
each test case, the first line contains a single integer N, denoting
there are N battleships of evil in a line. (1 <= N <= 100000)
  The
second line contains N integers Ei, indicating the endurance value of
each battleship from the beginning of the line to the end. You can
assume that the sum of all endurance value is less than 263.
  The next line contains an integer M, denoting the number of actions and queries. (1 <= M <= 100000)
  For
the following M lines, each line contains three integers T, X and Y.
The T=0 denoting the action of the secret weapon, which will decrease
the endurance value of the battleships between the X-th and Y-th
battleship, inclusive. The T=1 denoting the query of the commander which
ask for the sum of the endurance value of the battleship between X-th
and Y-th, inclusive.

Output

For
each test case, print the case number at the first line. Then print one
line for each query. And remember follow a blank line after each test
case.

Sample Input

10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8

Sample Output

Case #1: 19 7 6


思路:

  • 这题我一开始还是想用lazy标记做,因为我想每次都单点修改的话应该是会TLE的;
  • 但这题实在是没法做标记,因为每个点开方,对于一个区间是无法表示的,不像添加,减少和修改;
  • 有意思的地方就是每个点最大2^63,开方最多6、7次就一定可以达到1,1的话再怎么开方都是无用功,因此update的时候加个判断,如果sumv[o] == R - L + 1, 直接返回就行了;
  • 但这题最恶心的地方在于输入数据的L居然会比R大!


Code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define INF 0x3f3f3f3f
 4 #define M(a, b) memset(a, b, sizeof(a))
 5 #define lson o<<1
 6 #define rson o<<1|1
 7 const int maxn = 100000 + 10;
 8 int qL, qR;
 9 __int64 v, _sum;
10
11 struct SegmentTree {
12     __int64 sumv[maxn<<2];
13
14     void clear() {M(sumv, 0);}
15
16     void build(int o, int L, int R) {
17         if (L == R) {
18             scanf("%I64d", &v);
19             sumv[o] = v;
20         }
21         else {
22             int M = (L + R) >> 1;
23             build(lson, L, M);
24             build(rson, M+1, R);
25             sumv[o] = sumv[lson] + sumv[rson];
26         }
27     }
28
29     void maintain(int o, int L, int R) {
30         if (L < R) {
31             sumv[o] = sumv[lson] + sumv[rson];
32         }
33     }
34
35     void update(int o, int L, int R) {
36         if (qL <= L && R <= qR) {
37             if (sumv[o] == R - L + 1) return;
38         }
39         if (L == R) {
40             sumv[o] = (__int64)sqrt(sumv[o]);
41         }
42         else {
43             int M = (L + R) >> 1;
44             if (qL <= M) update(lson, L, M);
45             if (M < qR) update(rson, M+1, R);
46         }
47         maintain(o, L, R);
48     }
49
50     void query(int o, int L, int R) {
51         if (qL <= L && R <= qR) {
52             _sum += sumv[o];
53         }
54         else {
55             int M = (L + R) >> 1;
56             if (qL <= M) query(lson, L, M);
57             if (M < qR) query(rson, M+1, R);
58         }
59     }
60
61 };
62
63 SegmentTree T;
64
65 int main() {
66     int n, q, p, kase = 0;
67     while(~scanf("%d", &n)) {
68         printf("Case #%d:\n", ++kase);
69         T.clear();
70         T.build(1, 1, n);
71         scanf("%d", &q);
72         while(q--) {
73             scanf("%d", &p);
74             if (p) {
75                 scanf("%d%d", &qL, &qR);
76                 if (qL > qR) {int temp = qL; qL = qR; qR = temp;}
77                 _sum = 0;
78                 T.query(1, 1, n);
79                 printf("%I64d\n", _sum);
80             }
81             else {
82                 scanf("%d%d", &qL, &qR);
83                 if (qL > qR) {int temp = qL; qL = qR; qR = temp;}
84                 T.update(1, 1, n);
85             }
86         }
87         printf("\n");
88     }
89
90     return 0;
91 }
时间: 2024-08-04 20:23:56

HDU-Can you answer these queries? (线段树+区间修改)的相关文章

HDU 4027 Can you answer these queries? (线段树+区间点修改)

题意:给你 n 个数,m个询问(c,x,y) c==0 把x,y区间的值变为原来的平方根(向下取整) c==1 计算x,y区间的和. 利用1的开方永远为1剪枝.. #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> //#include<map> #include<cmath> #include<iostream> #include

HDU4027 Can you answer these queries 线段树区间求和+剪枝

给了你n,然后n个数字在一个数组中,接下来m个询问,每个询问三个数字 t,x,y,若t==0,那么修改区间[x,y]的每一个值,变为原来每个位置上的数 开根号取整,若t==1,那么对区间[x,y]求和 由于n,m,很大,所以树状数组铁定超时,若直接用线段树来做区间修改,那么也是超时,这类题目没别的方法了,静心剪枝,发现题目给的数据范围为2^63,有没有发现,2^63开根号 绝对不需要开10次,就能到1,到1以后就不需要再开了,意思就是若有某个区间[x,y]每一个点的值都为1时,这一段区间事实上是

HDU - 1698 Just a Hook (线段树区间修改)

Description In the game of DotA, Pudge's meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same length. Now Pudge wants to do some operations on the hook.

hdu 4027 Can you answer these queries? 线段树区间开根号,区间求和

Can you answer these queries? Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5195 Description A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use our secret weapo

HDU 4027 Can you answer these queries?(线段树 区间不等更新)

题意  输入n个数  然后有两种操作   输入0时将给定区间所有数都变为自己的开方   输入1输出给定区间所有数的和 虽然是区间更新  但每个点更新的不一样  因此只能对单点进行更新  其实一个点最多被更新7次  2^64开平方7次后就变为1了  如果某个区间的数都变为了1  那么对这个区间的开方就不用考虑了   另外要注意给你的区间可能是反的 #include <bits/stdc++.h> #define lc p<<1,s,mid #define rc p<<1|

HDU4027Can you answer these queries?(线段树区间和,坑)

Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 8674 Accepted Submission(s): 1971 Problem Description A lot of battleships of evil are arranged in a line before the b

【hdu】Just a Hook(线段树区间修改)

线段树模板题,练的是懒惰标记. 懒惰标记,就是更新一段区间的时候,如果小区间被包含在了所需要更新的区间里面,那么直接对代表这个区间的数组元素赋值,之后做一个标记(表示这个区间的子区间都需要更新)但是不继续递归(这样可以节省很多的时候). 11657115 2014-09-15 14:17:26 Accepted 1698 796MS 2380K 1750 B G++ KinderRiven #include<cstdio> #include<cstring> #include<

HDU - 3974 Assign the task (线段树区间修改+构建模型)

https://cn.vjudge.net/problem/HDU-3974 题意 有一棵树,给一个结点分配任务时,其子树的所有结点都能接受到此任务.有两个操作,C x表示查询x结点此时任务编号,T x y表示给x结点分配编号为y的任务. 分析 题目读起来就很有区间修改的味道,将一个区间变为一个值.问题在于怎么把这棵树对应到区间上. 对于一个结点,其控制的范围是它的子树,对应区间范围可以看作是以dfs序表示的区间.好像有点绕..就是给每个结点再对应一个dfs序,然后在dfs时把这个点控制的子树看

HDU 1166 —— Just a Hook 【线段树 区间修改】

http://acm.hdu.edu.cn/showproblem.php?pid=1698 要求: 1. 区间修改 2. 最后整个区间求和 分析: 因为没有多次查询,而只有最后的一次整个区间的求和查询,所以可以省去query查询函数. #include <cstdio> #include <iostream> #define lson rt << 1, l, m #define rson rt << 1 | 1, m+1, r using namespac