SPOJ GSS4 Can you answer these queries IV

Can you answer these queries IV

Time Limit: 5000ms

Memory Limit: 262144KB

This problem will be judged on SPOJ. Original ID: GSS4
64-bit integer IO format: %lld      Java class name: Main

You are given a sequence A of N(N <= 100,000) positive integers. There sum will be less than 1018. On this sequence you have to apply M (M <= 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.

Input

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 A1..AN. 
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.

Output

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.

Example

Input:
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

Output:
Case #1:
9
4
6

Case #2:
40
26

Source

Own problem, used in ACM/ICPC Regional Contest, Shanghai 2011 preliminary

解题:线段树

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn = 100010;
 5 struct node{
 6     int lt,rt;
 7     LL maxv,minv,sum,lazy;
 8     bool reset;
 9 }tree[maxn<<2];
10 inline void pushup(int v){
11     tree[v].maxv = max(tree[v<<1].maxv,tree[v<<1|1].maxv);
12     tree[v].minv = min(tree[v<<1].minv,tree[v<<1|1].minv);
13     tree[v].sum = tree[v<<1].sum + tree[v<<1|1].sum;
14 }
15 inline void pushdown(int v){
16     if(tree[v].reset){
17         tree[v<<1].sum = tree[v].lazy*(tree[v<<1].rt - tree[v<<1].lt + 1);
18         tree[v<<1].maxv = tree[v<<1|1].minv = tree[v].lazy;
19         tree[v<<1|1].sum = tree[v].lazy*(tree[v<<1|1].rt - tree[v<<1|1].lt + 1);
20         tree[v<<1|1].maxv = tree[v<<1|1].minv = tree[v].lazy;
21         tree[v].reset = false;
22     }
23 }
24 void build(int lt,int rt,int v){
25     tree[v].lt = lt;
26     tree[v].rt = rt;
27     tree[v].reset = false;
28     if(lt == rt){
29         scanf("%lld",&tree[v].maxv);
30         tree[v].minv = tree[v].sum = tree[v].maxv;
31         return;
32     }
33     int mid = (lt + rt)>>1;
34     build(lt,mid,v<<1);
35     build(mid + 1,rt,v<<1|1);
36     pushup(v);
37 }
38 void update(int lt,int rt,int v){
39     LL a = sqrt(tree[v].maxv*1.0),b = sqrt(tree[v].minv*1.0);
40     if(lt <= tree[v].lt && rt >= tree[v].rt && a == b){
41         tree[v].reset = true;
42         tree[v].sum = a*(tree[v].rt - tree[v].lt + 1);
43         tree[v].maxv = tree[v].minv = a;
44         tree[v].lazy = a;
45         return;
46     }
47     pushdown(v);
48     if(lt <= tree[v<<1].rt) update(lt,rt,v<<1);
49     if(rt >= tree[v<<1|1].lt) update(lt,rt,v<<1|1);
50     pushup(v);
51 }
52 LL query(int lt,int rt,int v){
53     if(lt <= tree[v].lt && rt >= tree[v].rt) return tree[v].sum;
54     pushdown(v);
55     LL ret = 0;
56     if(lt <= tree[v<<1].rt) ret = query(lt,rt,v<<1);
57     if(rt >= tree[v<<1|1].lt) ret += query(lt,rt,v<<1|1);
58     pushup(v);
59     return ret;
60 }
61 int main(){
62     int n,m,op,x,y,cs = 1;
63     while(~scanf("%d",&n)){
64         build(1,n,1);
65         scanf("%d",&m);
66         printf("Case #%d:\n",cs++);
67         while(m--){
68             scanf("%d%d%d",&op,&x,&y);
69             if(op) printf("%lld\n",query(x,y,1));
70             else update(x,y,1);
71         }
72     }
73     return 0;
74 }

时间: 2024-10-11 04:15:11

SPOJ GSS4 Can you answer these queries IV的相关文章

SPOJ GSS4 Can you answer these queries IV (线段树)

题目大意: 给出N个数 0     操作   把 l -----  r之间的数全部开平方 1     操作  输出 l -----r  之间的和 思路分析: 判断区间里的数字是否全相同.如果相同, 将cov 置为该数 查询的时候和更新的时候,如果碰到cov != -1 的  就直接返回就可以了 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #incl

Spoj 2713 Can you answer these queries IV 水线段树

题目链接:点击打开链接 题意: 给定n长的序列 下面2个操作 0 x y 给[x,y]区间每个数都 sqrt 1 x y 问[x, y] 区间和 #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #include <vector> #includ

SP2713 GSS4 - Can you answer these queries IV

传送门 \(ZHX\; TQL\) Orz 这道题目我们可以用线段树维护-- 可能有\(dalao\)会问:"线段树怎么维护区间开平方?" 而这道题的精髓就在于,它要我们维护的操作是开平方+下取整.也就是说经过一定的次数,要开平方的数会慢慢缩小为"\(1\)",这个次数是很小的,而\(\sqrt 1=1\). 所以在修改时,我们可以先查询这个区间是否全是"1",如果是,那我们就不管它,再去寻找其他的区间进行修改,如果这个区间里有其他数,我们就将这

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

题目链接:https://www.luogu.org/problemnew/show/SP2713 真暴力啊. 开方你开就是了,开上6次就都没了. #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define ll long long using namespace std; const int maxn

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

传送门 解题思路 大概就是一个数很少次数的开方会开到\(1\),而\(1\)开方还是\(1\),所以维护一个和,维护一个开方标记,维护一个区间是否全部为\(1/0\)的标记.然后每次修改时先看是否有全\(1\)或\(0\)的标记,有就不用理了,没有就暴力开方. 代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define int long long using

「SP2713」GSS4 - Can you answer these queries IV

传送门 Luogu 解题思路 区间开方以及区间求和. 考虑用线段树来做. 开方操作看似没有任何结合律可言,但这题有另外一个性质: 一个数的初始值不超过 \(10^{18}\) ,而这个数被开方6次左右就可以到1或0,并且1和0都是不需要再开方的. 所以我们记一下每个节点代表区间的最大值,若该值小于等于1,那么就不需要再进入下一层递归,否则就向下递归修改,修改次数最坏也不过是 \(O(6n)\) 左右,线段树完全没压力,于是这题就做完了. 细节注意事项 咕咕咕 参考代码 #include <alg

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

用计算器算一算,就可以发现\(10^{18}\)的数,被开方\(6\)次后就变为了\(1\). 所以我们可以直接暴力的进行区间修改,若这个数已经到达\(1\),则以后就不再修改(因为\(1\)开方后还是\(1\)),用并查集和树状数组进行维护. 这个方法用了P2391 白雪皑皑的思想处理,用并查集标记该点已经不再用替换. 和我这题CF920F[SUM和REPLACE]的方法相同. \(code\): #include<bits/stdc++.h> #define maxn 500010 #de

SPOJ 1043 Can you answer these queries I 求任意区间最大连续子段和 线段树

题目链接:点击打开链接 维护区间左起连续的最大和,右起连续的和.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lson

SPOJ 4487. Can you answer these queries VI splay

题目链接:点击打开链接 题意比较明显,不赘述. 删除时可以把i-1转到根,把i+1转到根下 则i点就在 根右子树 的左子树,且只有i这一个 点 #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; #define N 300500 #define inf 10000000 #define L(x) tree[x].ch[