P4145 上帝造题的七分钟2 / 花神游历各国(线段树区间开平方)

有点意思,不需要什么懒标记之类的东西,因为一个数无论怎样开平方,最后取整的结果必然会是1,所以我们不妨用最大值来维护,若区间最大值不为1,就暴力修改,否则不用管。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
struct node
{
    int l;
    int r;
    unsigned long long sum;
    unsigned long long mx;
}tree[maxn*4];
int n,m;
unsigned long long l,r,opt;
unsigned long long a[maxn];
void build(int now,int l,int r)
{
    tree[now].l=l;
    tree[now].r=r;
    if(l==r)
    {
        tree[now].sum=tree[now].mx=a[l];
        return;
    }
    int mid=(l+r)>>1; 
    build(now*2,l,mid);
    build(now*2+1,mid+1,r);
    tree[now].sum=tree[now*2].sum+tree[now*2+1].sum;
    tree[now].mx=max(tree[now*2].mx,tree[now*2+1].mx);
}
void update(int now,int l,int r)
{
    if(tree[now].l==tree[now].r)
    {
        tree[now].sum=sqrt(tree[now].sum);
        tree[now].mx=sqrt(tree[now].mx);
        return;
    }
    int mid=(tree[now].l+tree[now].r)>>1;
    if(l<=mid&&tree[now*2].mx>1)
    {
        update(now*2,l,r);
    }
    if(r>mid&&tree[now*2+1].mx>1)
    {
        update(now*2+1,l,r);
    }
    tree[now].sum=tree[now*2].sum+tree[now*2+1].sum;
    tree[now].mx=max(tree[now*2].mx,tree[now*2+1].mx);
}
long long query(int now,int l,int r)
{
    if(tree[now].l>=l&&tree[now].r<=r)
    {
        return tree[now].sum;
    }
    int mid=(tree[now].l+tree[now].r)>>1;
    long long ans=0;
    if(l<=mid)
    {
        ans+=query(now*2,l,r);
    }
    if(mid<r)
    {
        ans+=query(now*2+1,l,r);
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    build(1,1,n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld",&opt,&l,&r);
        if(l>r)
        {
            swap(l,r);
        }
        if(opt==0)
        {
            update(1,l,r);
        } 
        else
        {
            printf("%lld\n",query(1,l,r));
        }
    }
    return 0; 
}

多说几句,数据比较毒瘤,狂开unsigned long long 就能AC

posted @ 2019-04-27 14:04  JBLee  阅读(201)  评论(0编辑  收藏  举报