题意:
给定2个操作
0、把区间的每个数sqrt
2、求和
因为每个数的sqrt次数很少,所以直接更新到底,用个标记表示是否更新完全(即区间内的数字只有0,1就不用再更新了)
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define N 1000000
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define Val(x) tree[x].val
#define Ned(x) tree[x].ned
#define ll __int64
inline ll Mid(ll x,ll y){return (x+y)>>1;}
struct node{
ll l, r;
ll val;//这个区间需要被sqrt几次
bool ned;//如果为true则表示这个区间不管怎么开结果都一样
}tree[N*4];
ll n, a[101000];
void push_up(ll id){
Ned(id) = Ned(L(id))&&Ned(R(id));
Val(id) = Val(L(id))+Val(R(id));
}
void build(ll l, ll r, ll id){
tree[id].l = l; tree[id].r = r;
Ned(id) = false;
if(l==r){ Val(id) = a[l]; if(Val(id)<=1)Ned(id)=true; return ;}
ll mid = Mid(l,r);
build(l, mid, L(id));
build(mid+1,r,R(id));
push_up(id);
}
void update(ll l, ll r, ll id){
if(Ned(id))return;
if(l == tree[id].l && tree[id].r == r && l==r){
Val(id) = (ll)sqrt(1.0*Val(id));
if(Val(id)<=1)Ned(id)=1;
return;
}
ll mid = Mid(tree[id].l, tree[id].r);
if(r<=mid)
update(l,r,L(id));
else if(mid<l)
update(l,r,R(id));
else
{
update(l,mid,L(id));
update(mid+1,r,R(id));
}
push_up(id);
}
ll query(ll l, ll r, ll id){
if(tree[id].l == tree[id].r)return Val(id);
if(l == tree[id].l && tree[id].r == r && Ned(id))return Val(id);
ll mid = Mid(tree[id].l, tree[id].r);
if(r<=mid)return query(l,r,L(id));
else if(mid<l)return query(l,r,R(id));
else return query(l,mid,L(id))+query(mid+1,r,R(id));
}
int main(){
ll u, v, i, que, Cas = 1;
while(~scanf("%I64d",&n)){
for(i=1;i<=n;i++)scanf("%I64d",&a[i]);
build(1,n,1);
scanf("%I64d",&que);
printf("Case #%I64d:\n",Cas++);
while(que--){
scanf("%I64d %I64d %I64d",&i,&u,&v); if(u>v)swap(u,v);
if(i==0)
update(u,v,1);
else
printf("%I64d\n",query(u,v,1));
}
puts("");
}
return 0;
}
/*
10
1 2 3 4 5 6 7 8 9 10
99
1 10 10
0 2 8
*/HDU 4027 Can you answer these queries? 线段树裸题,布布扣,bubuko.com
HDU 4027 Can you answer these queries? 线段树裸题
原文地址:http://blog.csdn.net/acmmmm/article/details/25543923