线段树 SP2713 GSS4 - Can you answer these queries IV暨 【洛谷P4145】 上帝造题的七分钟2 / 花神游历各国

SP2713 GSS4 - Can you answer these queries IV

「题意」: n 个数,每个数在\(10^{18}\) 范围内。

现在有「两种」操作

0 x y把区间\([x,y]\) 内的每个数开方

1 x y询问区间\([x,y]\) 的每个数的和

「格式」: 有多组数据,数据以EOF结束,对于每组数据,输出数据的序号,每组数据之后输出一个空行。

「注意」: 不保证给出的区间\([x, y]\) 有x<=y ,如果x>y 请交换x ,y 。

之前做过花神那个题,但是是考试题,没有认真改。。。

模了大佬的题解才会。

原来真的是暴力,但是一个\(1*10^9\)的数最多开方5次就会降低到1到2之间。这个时候就不用开方了。

复杂度依旧是\(mlogn\),加了一个类似\(log\)的常数,差不多是5,6。

code:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define int long long
#define ls(o) o<<1
#define rs(o) o<<1|1
using namespace std;
const int wx=200017;
inline int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    return sum*f;
}
struct val_tree{
    int l,r,sum,ma;
    #define sum(o) t[o].sum
    #define ma(o) t[o].ma
}t[wx*4];
int a[wx];
int n,m;
void up(int o){
    sum(o)=sum(ls(o))+sum(rs(o));
    ma(o)=max(ma(ls(o)),ma(rs(o)));
}
void build(int o,int l,int r){
    t[o].l=l;t[o].r=r;
    if(l==r){sum(o)=ma(o)=a[l];return;}
    int mid=t[o].l+t[o].r>>1;
    if(l<=mid)build(ls(o),l,mid);
    if(r>mid)build(rs(o),mid+1,r);
    up(o);
}
void update(int o,int l,int r){
    if(t[o].l==t[o].r){
        sum(o)=(int)sqrt(sum(o));
        ma(o)=(int)sqrt(ma(o));
        return ;
    }
    int mid=t[o].l+t[o].r>>1;
    if(l<=mid&&ma(ls(o))>1)update(ls(o),l,r);
    if(r>mid&&ma(rs(o))>1)update(rs(o),l,r);
    up(o);
}
int query(int o,int l,int r){
    if(l<=t[o].l&&t[o].r<=r){
        return sum(o);
    }
    int mid=t[o].l+t[o].r>>1;
    int sum=0;
    if(l<=mid)sum+=query(ls(o),l,r);
    if(r>mid)sum+=query(rs(o),l,r);
    return sum;
}
signed main(){
    int cnt=0;
    while(~scanf("%lld",&n)){
        cnt++;
        memset(a,0,sizeof a);
        memset(t,0,sizeof t);
        printf("Case #%lld:\n",cnt);
        for(int i=1;i<=n;i++)a[i]=read();
        build(1,1,n);
        m=read();
        for(int i=1,opt,x,y;i<=m;i++){
            opt=read();x=read();y=read();
            if(x>y)swap(x,y);
            if(opt)printf("%lld\n",query(1,x,y));
            else update(1,x,y);
        }
        puts("");
    }
}

猜你喜欢

转载自www.cnblogs.com/wangxiaodai/p/9786759.html
今日推荐