BZOJ-3211-花神游历各国(线段树)
Description
Input
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
Source
题解
这道题和以前考的一道题差不多(那道题是区间取模)
这道题是区间开根,和取模相似的,开根次数也是有限的,所以我们可以用线段树来维护一段区间,当区间内都是0或1的时候就不用再做了
1 #include<bits/stdc++.h> 2 #define N 100005 3 #define ll long long 4 using namespace std; 5 int n,m; 6 int a[N]; 7 ll tree[4*N]; 8 bool flag[4*N]; 9 inline int read(){ 10 int x=0,f=1; char ch=getchar(); 11 while (ch>'9'||ch<'0'){ if (ch=='-') f=-1; ch=getchar(); } 12 while (ch<='9'&&ch>='0'){ x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } 13 return x*f; 14 } 15 void update(int v){ 16 tree[v]=tree[v<<1]+tree[v<<1|1]; 17 flag[v]=flag[v<<1]&flag[v<<1|1]; 18 } 19 void build(int v,int l,int r){ 20 if (l==r){ 21 tree[v]=a[l]; 22 if (a[l]<=1) flag[v]=1; 23 return; 24 } 25 int mid=(l+r)>>1; 26 build(v<<1,l,mid); 27 build(v<<1|1,mid+1,r); 28 update(v); 29 } 30 ll query(int v,int l,int r,int x,int y){ 31 if (x<=l&&y>=r) return tree[v]; 32 int mid=(l+r)>>1; 33 if (y<=mid) return query(v<<1,l,mid,x,y); else 34 if (x>mid) return query(v<<1|1,mid+1,r,x,y); else 35 return query(v<<1,l,mid,x,mid)+query(v<<1|1,mid+1,r,mid+1,y); 36 } 37 void change(int v,int l,int r,int x,int y){ 38 if (x<=l&&y>=r&&flag[v]) return; 39 if (l==r){ 40 tree[v]=(ll)sqrt(tree[v]); 41 if (tree[v]<=1) flag[v]=1; 42 return; 43 } 44 int mid=(l+r)>>1; 45 if (y<=mid) change(v<<1,l,mid,x,y); else 46 if (x>mid) change(v<<1|1,mid+1,r,x,y); else{ 47 change(v<<1,l,mid,x,mid); 48 change(v<<1|1,mid+1,r,mid+1,y); 49 } 50 update(v); 51 } 52 int main(){ 53 n=read(); 54 for (int i=1;i<=n;i++) a[i]=read(); 55 build(1,1,n); 56 m=read(); 57 for (int i=1;i<=m;i++){ 58 int x=read(),l=read(),r=read(); 59 if (x==1) printf("%lld\n",query(1,1,n,l,r)); 60 else change(1,1,n,l,r); 61 } 62 return 0; 63 }