zoukankan      html  css  js  c++  java
  • 【题解】[UOJ 228] 基础数据结构练习题【线段树 均摊数据结构】

    题目链接

    题意

    维护序列:

    • 区间求和;
    • 区间加;
    • 区间开根并下取整。

    (n,mleq 10^5)(a_ileq 10^5)

    题解

    注意到开根并下取整会让一个区间的数的差变小。于是额外维护区间最大最小值,当所有数相同时转化为区间减。

    特殊情况:(n^2,n^2-1,n^2,n^2-1) 这样的序列反复进行操作 2,3 会一直保持极差为 1,于是特判一下,同样化为区间减。

    复杂度均摊一下就对了。

    #include<bits/stdc++.h>
    using namespace std;
    const int BUF_LEN=1<<19;
    struct FastIO{
        char bufi[BUF_LEN+10],*PTi=bufi+BUF_LEN,*PTENDi=bufi+BUF_LEN;
        inline char gc(){
            (PTi==PTENDi)&&(bufi[fread(bufi,1,BUF_LEN,stdin)]=0,PTi=bufi);
            return *(PTi++);
        }
        char bufo[BUF_LEN+10],*PTo=bufo,*PTENDo=bufo+BUF_LEN;
        inline void pc(char c){
            (PTo==PTENDo)&&(fwrite(bufo,1,BUF_LEN,stdout),PTo=bufo);
            *(PTo++)=c;
        }
        void flush(){
            fwrite(bufo,1,PTo-bufo,stdout);
            PTo=bufo;
        }
        ~FastIO(){
            flush();
        }
    
        template<class T>inline void getint(T &x=0){
            char c=gc();
            int f=1;x=0;
            while(c<'0'||c>'9'){
                if(c=='-')f=-1;
                c=gc();
            }
            while(c>='0'&&c<='9'){
                x=x*10+c-'0'; 
                c=gc();
            }
            if(f==-1)x=-x;
        }
        operator int(){
            int v;getint(v);return v;
        }
        operator long long(){
            long long v;getint(v);return v;
        }
        template<class T>inline void putint(T x=0,char sep=' '){
            char tmp[20],len=0;
            if(x<0)pc('-'),x=-x;
            if(x==0){ pc('0');pc(sep);return; }
            while(x)tmp[len++]=x%10,x/=10;
            for(int i=len-1;~i;--i)pc(tmp[i]|'0');
            pc(sep);
        }
    }io;
    
    const int N=2e5+10;
    #define ll long long
    #define int long long
    ll mx[N<<2],mn[N<<2],sum[N<<2],tag[N<<2];
    void pushup(int x){
        sum[x]=sum[x<<1]+sum[x<<1|1];
        mx[x]=max(mx[x<<1],mx[x<<1|1]);
        mn[x]=min(mn[x<<1],mn[x<<1|1]);
    }
    void pushdown(int x,int l,int r){
        int mid=l+r>>1;
        mx[x<<1]+=tag[x];
        mx[x<<1|1]+=tag[x];
        mn[x<<1]+=tag[x];
        mn[x<<1|1]+=tag[x];
        sum[x<<1]+=tag[x]*(mid-l+1);
        sum[x<<1|1]+=tag[x]*(r-mid);
        tag[x<<1]+=tag[x];
        tag[x<<1|1]+=tag[x];
        tag[x]=0;
    }
    
    void mdf1(int l,int r,int v,int x,int nl,int nr){
        if(nr<l||nl>r)return;
        if(l<=nl&&nr<=r){
            mx[x]+=v;
            mn[x]+=v;
            sum[x]+=(nr-nl+1ll)*v;
            tag[x]+=v;
            return ;
        }
        pushdown(x,nl,nr);
        int mid=nl+nr>>1;
        mdf1(l,r,v,x<<1,nl,mid);
        mdf1(l,r,v,x<<1|1,mid+1,nr);
        pushup(x);
    }
    void mdf2(int l,int r,int x,int nl,int nr){
        if(nr<l||nl>r)return;
        pushdown(x,nl,nr);
        if(l<=nl&&nr<=r){
            if(mx[x]==mn[x]){
                mdf1(nl,nr,(ll)(sqrt(mx[x]))-mx[x],x,nl,nr);
                return;
            }
            if(mx[x]==mn[x]+1&&(ll)(sqrt(mx[x]))==(ll)(sqrt(mn[x]))+1){
                mdf1(nl,nr,(ll)(sqrt(mx[x]))-mx[x],x,nl,nr);
                return;
            }
        }
        int mid=nl+nr>>1;
        mdf2(l,r,x<<1,nl,mid);
        mdf2(l,r,x<<1|1,mid+1,nr);
        pushup(x);
    }
    ll query(int l,int r,int x,int nl,int nr){
        if(nr<l||nl>r)return 0;
        if(l<=nl&&nr<=r)return sum[x];
        pushdown(x,nl,nr);
        int mid=nl+nr>>1;
        return query(l,r,x<<1,nl,mid)+query(l,r,x<<1|1,mid+1,nr);
    }
    int a[N];
    void build(int x,int l,int r){
        if(l==r){
            mx[x]=mn[x]=sum[x]=a[l];
            return;
        }
        int mid=l+r>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        pushup(x);
    }
    signed main(){
        int n=io,m=io;
        for(int i=1;i<=n;i++)a[i]=io;
        build(1,1,n);
        while(m--){
            int tp=io;
            if(tp==1){
                int l=io,r=io,x=io;
                mdf1(l,r,x,1,1,n);
            }
            if(tp==2){
                int l=io,r=io;
                mdf2(l,r,1,1,n);
            }
            if(tp==3){
                int l=io,r=io;
                io.putint(query(l,r,1,1,n),'
    ');
            }
        }
    }
    
    
  • 相关阅读:
    Exception in thread "main" java.lang.IllegalArgumentException:解决方法
    Warning: $HADOOP_HOME is deprecated.解决方法
    Android :TextView使用SpannableString设置复合文本
    一、harbor部署之centos7的基本配置
    木马基础知识要点
    【原创】红客闯关游戏部分题解
    【原创】利用Office宏实现powershell payload远控
    【原创】字典攻击教务处(BurpSuite使用)
    【原创】逆向练习(CrackMe)
    显式游标和隐式游标二者的区别
  • 原文地址:https://www.cnblogs.com/wallbreaker5th/p/14251416.html
Copyright © 2011-2022 走看看