题目链接~~>
做题感悟:这题是在还没去西安比赛的时候做的练习赛,做时是学长想的思路,感觉自己弱爆了,这题想法确实挺好。
解题思路:
猛的一看貌似很难的样子,但是只要细心一点你就会找到突破口,因为每个数最多开方 63 次 ,这样我们可以每次更新区间的时候直接暴力到叶子节点,但是只这样是不行的,还要用一个标记,记录整个区间是否还需要开方。注意:开方的时候开方的数要乘以1.0 ,题目给的区间不一定是 x < y ,需要判断一下。
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<sstream> #include<map> #include<cmath> #include<fstream> #include<queue> #include<vector> #include<sstream> #include<cstring> #include<cstdio> #include<stack> #include<bitset> #include<ctime> #include<string> #include<cctype> #include<iomanip> #include<algorithm> using namespace std ; #define INT __int64 #define L(x) (x * 2) #define R(x) (x * 2 + 1) const int INF = 0x3f3f3f3f ; const double esp = 0.0000000001 ; const double PI = acos(-1.0) ; const INT mod = 1000000007 ; const int MY = 10 + 5 ; const int MX = 100000 + 5 ; int n ,m ; struct node { int le ,rt ; bool flag ; INT c ; }T[MX*4] ; void build(int i ,int le ,int rt) // 建树 { T[i].le = le ; T[i].rt = rt ; T[i].flag = false ; if(le == rt) { scanf("%I64d" ,&T[i].c) ; if(T[i].c <= 1) T[i].flag = true ; // 代表不用开方了 return ; } int Mid = (T[i].le + T[i].rt)>>1 ; build(L(i) ,le ,Mid) ; build(R(i) ,Mid+1 ,rt) ; T[i].c = T[L(i)].c + T[R(i)].c ; T[i].flag = T[L(i)].flag&T[R(i)].flag ; } void section(int i ,int le ,int rt) // 给区间开方 { if(T[i].flag) return ; if(T[i].le == T[i].rt) // 直接暴力到叶子节点 { if(!T[i].flag) // 代表还可以开方 T[i].c = (INT)sqrt(T[i].c*1.0) ; if(T[i].c <= 1) // 判断是否还可以开方 T[i].flag = true ; return ; } int Mid = (T[i].le + T[i].rt)>>1 ; if(le > Mid) section(R(i) ,le ,rt) ; else if(rt <= Mid) section(L(i) ,le ,rt) ; else { section(L(i) ,le ,Mid) ; section(R(i) ,Mid+1 ,rt) ; } T[i].c = T[L(i)].c + T[R(i)].c ; T[i].flag = T[L(i)].flag&T[R(i)].flag ; } INT Query(int i ,int le ,int rt) { if(T[i].le == le && T[i].rt == rt) return T[i].c ; int Mid = (T[i].le + T[i].rt)>>1 ; if(le > Mid) return Query(R(i) ,le ,rt) ; else if(rt <= Mid) return Query(L(i) ,le ,rt) ; else return Query(L(i) ,le ,Mid) + Query(R(i) ,Mid+1 ,rt) ; } int main() { //freopen("input.txt" ,"r" ,stdin) ; int p ,u ,v ,cse = 1 ; while(~scanf("%d" ,&n)) { build(1 ,1 ,n) ; scanf("%d" ,&m) ; printf("Case #%d:\n" ,cse++) ; for(int i = 0 ;i < m ; ++i) { scanf("%d%d%d" ,&p ,&u ,&v) ; if(u > v) swap(u ,v) ; if(p) printf("%I64d\n" ,Query(1 ,u ,v)) ; else section(1 ,u ,v) ; } printf("\n") ; } return 0 ; }