#10128. 「一本通 4.3 练习 2」花神游历各国

2019-01-28 13:31:24


10128. 「一本通 4.3 练习 2」花神游历各国

题意

每一次旅行中,花神会选择一条旅游路线,它在那一串国家中是连续的一段,这次旅行带来的开心值是这些国家的喜欢度的总和,当然花神对这些国家的喜欢程序并不是恒定的,有时会突然对某些国家产生反感,使他对这些国家的喜欢度 $\delta$ 变为 $\sqrt \delta$ (可能是花神虐爆了那些国家的 OI,从而感到乏味)。

现在给出花神每次的旅行路线,以及开心度的变化,请求出花神每次旅行的开心值。

思路

为了使时间复杂度降低,我们可以发现:​ $\sqrt 1=1$ 所以,最大数字 $10^9$ 操作较少次数便能到 $1$ 。所以在操作前判断一下,如果区间内都是 $1$ 即可跳过。

#include<bits/stdc++.h>
#define ll long long
#define MAXNUM 1000000*4+10
using namespace std;
struct node{
    ll l,r,lef,rig;
    ll val,Max;
}tree[210000];
ll a[110000],len,n,m;
void build(ll l,ll r){
    ll root=++len;
    tree[root].l=l;tree[root].r=r;tree[root].lef=tree[root].rig=-1;
    if(l==r)tree[root].val=tree[root].Max=a[l];
    else{
        ll mid=(l+r)/2;
        ll lef=tree[root].lef=len+1;build(l,mid);
        ll rig=tree[root].rig=len+1;build(mid+1,r);
        tree[root].val=tree[lef].val+tree[rig].val;
        tree[root].Max=max(tree[lef].Max,tree[rig].Max);
    }
}
void update(ll root,ll l,ll r){
    if(tree[root].Max<2) return ;
    if(tree[root].l==tree[root].r){tree[root].val=sqrt(tree[root].val);tree[root].Max=tree[root].val;return ;}
    ll lef=tree[root].lef,rig=tree[root].rig,mid=(tree[root].l+tree[root].r)/2;
    if(r<=mid) update(lef,l,r);
    else if(mid<l) update(rig,l,r);
    else update(lef,l,mid),update(rig,mid+1,r);
    tree[root].val=tree[lef].val+tree[rig].val;
    tree[root].Max=max(tree[lef].Max,tree[rig].Max);
}
ll query(ll root,ll l,ll r){
    if(tree[root].l>=l&&tree[root].r<=r) return tree[root].val;
    ll lef=tree[root].lef,rig=tree[root].rig,mid=(tree[root].l+tree[root].r)/2;
    if(r<=mid) return query(lef,l,r);
    else if(mid<l) return query(rig,l,r);
    else return query(lef,l,mid)+query(rig,mid+1,r);
}
int main(){
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
    build(1,n);
    scanf("%lld",&m);
    while(m--){
        char s;cin>>s;
        if(s=='2'){
            ll x,y;scanf("%lld%lld",&x,&y);
            update(1,x,y);
        }else{
            ll x,y;scanf("%lld%lld",&x,&y);
            printf("%lld\n",query(1,x,y));
        }
    }
    return 0;
}