/*
一个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;
}
转载于:https://www.cnblogs.com/nkhelloworld/archive/2011/09/29/2195262.html