题目链接:
HDU 4027 Can you answer these queries?
分析:
long
long
范围内每个数最多开8次方就会变为1,当当前区间所有数都变为1了,就不需要更新了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=100010;
int n,m,t,a,b,cases=0;
long long ans;
long long val[maxn];
struct SegTree{
int left,right;
long long val;
}segtree[maxn<<2];
void build(int left,int right,int cur)
{
segtree[cur].left=left;
segtree[cur].right=right;
if(left==right)
{
segtree[cur].val=val[left];
return;
}
int mid=(left+right)>>1;
build(left,mid,cur<<1);
build(mid+1,right,(cur<<1)|1);
segtree[cur].val=segtree[cur<<1].val+segtree[(cur<<1)|1].val;
}
void update(int a,int b,int cur)
{
int left=segtree[cur].left;
int right=segtree[cur].right;
if(segtree[cur].val==right-left+1) return ;//区间所有值都是1,那么开根号后还是1,就不用更新了
if(left==right)
{
segtree[cur].val=(int)(sqrt(1.0*segtree[cur].val));
return ;
}
int mid=(left+right)>>1;
if(b<=mid) update(a,b,cur<<1);
else if(a>mid) update(a,b,(cur<<1)|1);
else
{
update(a,mid,cur<<1);
update(mid+1,b,(cur<<1)|1);
}
segtree[cur].val=segtree[cur<<1].val+segtree[(cur<<1)|1].val;
}
void query(int a,int b,int cur)
{
int left=segtree[cur].left;
int right=segtree[cur].right;
long long val=segtree[cur].val;
if(left==a&&right==b)
{
ans+=val;
return;
}
int mid=(left+right)>>1;
if(b<=mid) query(a,b,cur<<1);
else if(a>mid) query(a,b,(cur<<1)|1);
else
{
query(a,mid,cur<<1);
query(mid+1,b,(cur<<1)|1);
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%I64d",&val[i]);
build(1,n,1);
scanf("%d",&m);
printf("Case #%d:\n",++cases);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&t,&a,&b);
if(a>b) swap(a,b);
if(t==0)
update(a,b,1);
else
{
ans=0;
query(a,b,1);
printf("%I64d\n",ans);
}
}
printf("\n");
}
return 0;
}