刷题向》关于线段树的区间开根号 BZOJ3211(NORMAL+)
这是一道关于线段树的区间开根号的裸题,没什么好讲的。
值得注意的是,因为有区间开根号的性质,所以我们每一次更改操作只能把更改区间所覆盖的所有元素全部查找,当然你直接找效率明显爆炸。。。
能够注意到,指数级别的操作一次更改的数字都很大,而题目的数字最大是10的9次,所以可以注意到的是当一个区间更新6遍以后就失去更新的意义了,因为当你更改次数超过6次所有非负整数数字就全部会化为1。所以可以在每一个节点上加一个类似于LAZY标记的东西,记录开根号次数,以便节约跟新时间。
贴出题目&代码
Description
线段树区间开根号与求和
Input
第一行N代表有N个数
第二行有N个数,代表这N个值分别是多少
第三行有一个M
接下来M行,每行有X,L,R
当X为1代表求区间:(L,R)的和。
当X为2代表对区间:(L,R)开根号。
Output
每次x=1时,每行一个整数,表示区间和
Sample Input
4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
Sample Output
101
11
11
11
11
HINT
对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9
1 /************************************************************** 2 Problem: 3211 3 User: PencilWang 4 Language: C++ 5 Result: Accepted 6 Time:1996 ms 7 Memory:9036 kb 8 ****************************************************************/ 9 10 #include<cstdio> 11 #include<cmath> 12 int n,m; 13 struct shit{ 14 int L,R,t; 15 long long num; 16 }s[400100]; 17 int w[100100]; 18 void push_up(int p) 19 { 20 s[p].num=s[p<<1].num+s[p<<1|1].num; 21 return ; 22 } 23 void build(int p,int l,int r) 24 { 25 s[p].L=l; 26 s[p].R=r; 27 if(l==r) 28 { 29 s[p].num=w[l]; 30 return ; 31 } 32 int mid=(l+r)>>1; 33 build(p<<1,l,mid); 34 build(p<<1|1,mid+1,r); 35 push_up(p); 36 return ; 37 } 38 void fuck(int p,int a,int b) 39 { 40 if(a<=s[p].L&&s[p].R<=b) 41 { 42 s[p].t++; 43 if(s[p].L==s[p].R) 44 { 45 s[p].num=sqrt(s[p].num); 46 return ; 47 } 48 } 49 int mid=(s[p].L+s[p].R)>>1; 50 if(s[p<<1].t<6&&a<=mid)fuck(p<<1,a,b); 51 if(s[p<<1|1].t<6&&b>mid)fuck(p<<1|1,a,b); 52 push_up(p); 53 return ; 54 } 55 long long Q(int p,int a,int b) 56 { 57 if(a<=s[p].L&&s[p].R<=b) 58 { 59 return s[p].num; 60 } 61 long long ans=0; 62 int mid=(s[p].L+s[p].R)>>1; 63 if(a<=mid) ans+=Q(p<<1,a,b); 64 if(b>mid)ans+=Q(p<<1|1,a,b); 65 return ans; 66 } 67 int main() 68 { 69 int a,b,f; 70 scanf("%d",&n); 71 for(int i=1;i<=n;i++)scanf("%d",w+i); 72 scanf("%d",&m); 73 build(1,1,n); 74 while(m--) 75 { 76 scanf("%d%d%d",&f,&a,&b); 77 if(f-1)fuck(1,a,b); 78 else printf("%lld\n",Q(1,a,b)); 79 } 80 return 0; 81 }