【UOJ228】基础数据结构练习题[线段树]

【UOJ228基础数据结构练习题】

==看到开根 第一反应之前那个区间开根 每个数最多只会开5次

可是这题又有加法操作 如果这次开完 下一次又加回来不断循环就爆炸了

如果一段区间的数开方后减少的值相同 我们就可以转化为区间减法 这样复杂度就可以保证了==

比如8 9开方后是2 3减少的值都为6

所以线段树还要再维护区间最大和最小 每次开方时特判其减少的值是否相等

yyb大佬的总结

这类题目的重点在于这些特殊操作的处理

此时的思考的主要方向已经不是线段树如何使用了

而是想清楚当前操作具有的特殊性质

再来相应地在线段树上维护所需要的东西

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)>(y)?(y):(x))
#define ls (o<<1)
#define rs (o<<1|1)
const int N=1e5+5,M=32000+5,inf=0x3f3f3f3f;
int n,m,a[N],b[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

struct node{ll mx,mn,add,sum;}t[N<<2];
void pup(int o){
    t[o].sum=t[ls].sum+t[rs].sum;
    t[o].mx=Max(t[ls].mx,t[rs].mx);
    t[o].mn=Min(t[ls].mn,t[rs].mn);
}
void updnode(int o,int l,int r,ll k){
    t[o].sum+=(ll)(r-l+1)*k;
    t[o].add+=k,t[o].mn+=k,t[o].mx+=k;
}
void pudw(int o,int l,int r){
    int mid=l+r>>1;
    if(t[o].add!=0) updnode(ls,l,mid,t[o].add),updnode(rs,mid+1,r,t[o].add),t[o].add=0;
}

void upd1(int o,int l,int r,int x,int y,ll k){
    if(l>y||r<x) return;
    if(x<=l&&r<=y){updnode(o,l,r,k);return;}
    pudw(o,l,r);
    int mid=l+r>>1;
    upd1(ls,l,mid,x,y,k),upd1(rs,mid+1,r,x,y,k);
    pup(o);
}
void upd2(int o,int l,int r,int x,int y){
    if(l>y||r<x) return;
    if(x<=l&&r<=y){
        ll A=t[o].mn-(ll)sqrt(t[o].mn),B=t[o].mx-(ll)sqrt(t[o].mx);
        if(A==B){updnode(o,l,r,-A);return;}
    }
    pudw(o,l,r);
    int mid=l+r>>1;
    upd2(ls,l,mid,x,y),upd2(rs,mid+1,r,x,y);
    pup(o);
}
ll query(int o,int l,int r,int x,int y){
    if(l>y||r<x) return 0;
    if(x<=l&&r<=y) return t[o].sum;
    pudw(o,l,r);
    int mid=l+r>>1;ll ans=0ll;
    ans+=query(ls,l,mid,x,y)+query(rs,mid+1,r,x,y);
    pup(o);
    return ans;
}
void build(int o,int l,int r){
    t[o].add=0;
    if(l==r){t[o].mn=t[o].mx=t[o].sum=a[l];return;}
    int mid=l+r>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    pup(o);
}

int main(){
    freopen("in.txt","r",stdin);
//  freopen("numbers.out","w",stdout);
    rd(n),rd(m);
    for(int i=1;i<=n;++i) rd(a[i]);
    build(1,1,n);
    for(int i=1,opt,x,y,k;i<=m;++i){
        rd(opt),rd(x),rd(y);
        if(opt==1)
            rd(k),upd1(1,1,n,x,y,k);
        else if(opt==2) upd2(1,1,n,x,y);
        else printf("%lld\n",query(1,1,n,x,y));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lxyyyy/p/11446912.html