洛谷 P4145 上帝造题的七分钟2 / 花神游历各国
题目链接
题目描述
题目分析
这道题实际上是一道动态RSQ(区间求和问题),很容易想到使用线段树来解决。但我们发现,和的开方并不等于开方的和,也就是说我们不能够通过直接对某一段区间的和进行开方来改变某一个区间的喜欢度——我们只能对区间里的每一个值分别进行更改再求和。
但这样的区间修改的时间复杂度难以承受。于是我们要寻求优化的方法。我们注意到,sqrt(1)=1,也就是说对于1开方的过程是可以省略的。由于数列中的数均为正整数,如果区间的和等于区间的长度,就说明区间里所有数均为1,那么我们就可以不用修改这个区间从而剪枝。
代码
1 #include<algorithm> 2 #include<cmath> 3 #include<cstdio> 4 using namespace std; 5 long long n,m,x,order,t1,t2,sumof[400001]; 6 void fastinput(long long &temp) 7 { 8 temp=0; 9 char now=getchar(); 10 while(now<'0'||now>'9') 11 now=getchar(); 12 while(now>='0'&&now<='9') 13 { 14 temp=temp*10+now-'0'; 15 now=getchar(); 16 } 17 return; 18 } 19 void fastoutput(long long temp) 20 { 21 if(temp>9) 22 fastoutput(temp/10); 23 putchar(temp%10+'0'); 24 return; 25 } 26 void fastoutputln(long long temp) 27 { 28 fastoutput(temp); 29 putchar('\n'); 30 return; 31 } 32 void add(long long no,long long l,long long r,long long place,long long value) 33 { 34 if(place>r||place<l) 35 return; 36 if(l==r&&l==place) 37 { 38 sumof[no]+=value; 39 return; 40 } 41 long long mid=l+r>>1; 42 add(no<<1,l,mid,place,value); 43 add(no<<1|1,mid+1,r,place,value); 44 sumof[no]=sumof[no<<1]+sumof[no<<1|1]; 45 return; 46 } 47 void change(long long no,long long l,long long r,long long x,long long y) 48 { 49 if(sumof[no]<=r-l+1) 50 return; 51 if(x>r||y<l) 52 return; 53 if(l==r&&x<=l&&r<=y) 54 { 55 sumof[no]=(long long)sqrt(sumof[no]); 56 return; 57 } 58 long long mid=l+r>>1; 59 change(no<<1,l,mid,x,y); 60 change(no<<1|1,mid+1,r,x,y); 61 sumof[no]=sumof[no<<1]+sumof[no<<1|1]; 62 return; 63 } 64 long long query(long long no,long long l,long long r,long long x,long long y) 65 { 66 if(x<=l&&r<=y) 67 return sumof[no]; 68 long long mid=l+r>>1,result=0LL; 69 if(x<=mid) 70 result+=query(no<<1,l,mid,x,y); 71 if(mid<y) 72 result+=query(no<<1|1,mid+1,r,x,y); 73 return result; 74 } 75 int main() 76 { 77 fastinput(n); 78 for(long long i=1;i<=n;++i) 79 { 80 fastinput(x); 81 add(1,1,n,i,x); 82 } 83 fastinput(m); 84 for(long long i=1;i<=m;++i) 85 { 86 fastinput(order); 87 fastinput(t1); 88 fastinput(t2); 89 if(t1>t2) 90 swap(t1,t2); 91 if(order==1) 92 fastoutputln(query(1,1,n,t1,t2)); 93 else 94 change(1,1,n,t1,t2); 95 } 96 return 0; 97 }