/* 一个10^5的序列,有10^5个操作,每个操作为a,b,c a=0时将b到c区间内的数都开根号下取整,a=1时求b到c段的和 其中所有数的和不超过2^63。 可以发现所有的数最多开7次方,就会变成1了,再开方就不变了。 所以定一个标记allone表示这一段已经全是1了,以后的开房遇到allone为true就不向下进行了,提高效率。 线段树求和的变型,线段树提高效率的关键在于寻找合适的lazy标记,到满足一定条件的时候就不继续更新到点。 *注意在HDOJ里,64位整数,定义用__int64或longlong,输入输出只能用%I64d */ //4675978 2011-09-29 08:46:46 Accepted 4027 734MS 6368K 2308 B G++ nkhelloworld //4675979 2011-09-29 08:46:53 Accepted 4027 437MS 6424K 2308 B C++ nkhelloworld #include <cstdio> #include <cmath> #define MAXN 100010 struct SEGMENTTREE { int lt,rt; long long sum; bool allone; }tree[MAXN*4+1]; int n,m; void swap(int &a,int &b) { int t = a; a = b; b = t; } void buildsegtree(int root,int lt,int rt) { tree[root].lt = lt; tree[root].rt = rt; if(lt == rt) { scanf("%I64d",&tree[root].sum); if(tree[root].sum == 1) tree[root].allone = true; else tree[root].allone = false; return ; } int mid = (lt + rt)>>1; buildsegtree(root<<1, lt, mid); buildsegtree(root<<1|1, mid+1, rt); tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum; tree[root].allone = tree[root<<1].allone & tree[root<<1|1].allone; } void update(int root,int lt,int rt) { if(tree[root].allone) return ; if(tree[root].lt == tree[root].rt) { tree[root].sum = (long long)(sqrt((double)tree[root].sum)); if(tree[root].sum == 1) tree[root].allone = true; return ; } int mid = (tree[root].lt + tree[root].rt)>>1; if(rt <= mid) update(root<<1,lt,rt); else if(lt > mid) update(root<<1|1,lt,rt); else { update(root<<1,lt,mid); update(root<<1|1,mid+1,rt); } tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum; tree[root].allone = tree[root<<1].allone & tree[root<<1|1].allone; } long long query(int root,int lt,int rt) { if(tree[root].lt == lt && tree[root].rt == rt) return tree[root].sum; int mid = (tree[root].lt + tree[root].rt)>>1; if(rt <= mid) return query(root<<1,lt,rt); else if(lt > mid) return query(root<<1|1,lt,rt); else { return query(root<<1,lt,mid) + query(root<<1|1,mid+1,rt); } } int main() { int a,b,c,numcase = 0; while(scanf("%d",&n)!=EOF) { printf("Case #%d:\n",++numcase); buildsegtree(1,1,n); scanf("%d",&m); while(m--) { scanf("%d%d%d",&a,&b,&c); if(b>c) swap(b,c); if(a == 0) update(1,b,c); else printf("%I64d\n",query(1,b,c)); } printf("\n"); } return 0; }