题意:
给定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
时间: 2024-10-22 09:52:08