zoukankan      html  css  js  c++  java
  • 线段树练习5(codevs 4927)

    题目描述 Description

    有n个数和5种操作

    add a b c:把区间[a,b]内的所有数都增加c

    set a b c:把区间[a,b]内的所有数都设为c

    sum a b:查询区间[a,b]的区间和

    max a b:查询区间[a,b]的最大值

    min a b:查询区间[a,b]的最小值

    输入描述 Input Description

    第一行两个整数n,m,第二行n个整数表示这n个数的初始值

    接下来m行操作,同题目描述

    输出描述 Output Description

    对于所有的sum、max、min询问,一行输出一个答案

    样例输入 Sample Input

    10 6

    3 9 2 8 1 7 5 0 4 6

    add 4 9 4

    set 2 6 2

    add 3 8 2

    sum 2 10

    max 1 7

    min 3 6

    样例输出 Sample Output

    49

    11

    4

    数据范围及提示 Data Size & Hint

    10%:1<n,m<=10

    30%:1<n,m<=10000

    100%:1<n,m<=100000

    保证中间结果在long long(C/C++)、int64(pascal)范围内

    /*
      线段树的裸题,用分块写略麻烦。
      对于每个块维护两个标记,添加标记和修改标记,修改的时候对于完整的块只修改标记,对于不完整的块,暴力修改,查询也是一样。 
    */
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #define N 100010
    #define inf 1000000000
    #define lon long long
    using namespace std;
    int val[N],mx[N],mn[N],tag1[N],tag2[N],bl[N],n,m,len;lon sum[N];
    
    void pushdown(int k){
        if(tag2[k]!=-1){
            for(int i=(k-1)*len+1;i<=min(k*len,n);i++)
                val[i]=tag2[k];
            tag1[k]=0;tag2[k]=-1;
        }
        if(tag1[k]){
            for(int i=(k-1)*len+1;i<=min(k*len,n);i++)
                val[i]+=tag1[k];
            tag1[k]=0;
        }
    }
    
    void modify(int x,int y,int z){
        //下放x不完整区间
        int k=bl[x];pushdown(k);
        for(int i=x;i<=min(k*len,y);i++) val[i]+=z;
        sum[k]=0;mx[k]=-inf;mn[k]=inf;
        for(int i=(k-1)*len+1;i<=min(k*len,n);i++)
            sum[k]+=(lon)val[i],mx[k]=max(mx[k],val[i]),mn[k]=min(mn[k],val[i]);
        //下放完整区间 
        for(int i=bl[x]+1;i<bl[y];i++){
            if(tag2[i]!=-1) tag2[i]+=z;
            else tag1[i]+=z;
            sum[i]+=(lon)z*(lon)len;mx[i]+=z;mn[i]+=z; 
        }
        //下放y不完整区间 
        if(bl[x]==bl[y]) return;
        k=bl[y];pushdown(k);
        for(int i=(k-1)*len+1;i<=y;i++) val[i]+=z;
        sum[k]=0;mx[k]=-inf;mn[k]=inf;
        for(int i=(k-1)*len+1;i<=min(k*len,n);i++)
            sum[k]+=(lon)val[i],mx[k]=max(mx[k],val[i]),mn[k]=min(mn[k],val[i]);
    }
    
    void change(int x,int y,int z){
        //下放x不完整区间 
        int k=bl[x];pushdown(k);
        for(int i=x;i<=min(k*len,y);i++) val[i]=z;
        sum[k]=0;mx[k]=-inf;mn[k]=inf;
        for(int i=(k-1)*len+1;i<=min(k*len,n);i++)
            sum[k]+=(lon)val[i],mx[k]=max(mx[k],val[i]),mn[k]=min(mn[k],val[i]);
        //下方完整区间
        for(int i=bl[x]+1;i<bl[y];i++)
            tag2[i]=mx[i]=mn[i]=z,sum[i]=(lon)z*(lon)len,tag1[i]=0;
        //下放y不完整区间
        if(bl[x]==bl[y]) return;
        k=bl[y];pushdown(k);
        for(int i=(k-1)*len+1;i<=y;i++) val[i]=z;
        sum[k]=0;mx[k]=-inf;mn[k]=inf;
        for(int i=(k-1)*len+1;i<=min(k*len,n);i++)
            sum[k]+=(lon)val[i],mx[k]=max(mx[k],val[i]),mn[k]=min(mn[k],val[i]);
    }
    
    lon querysum(int x,int y){
        lon tot=0;int k=bl[x];
        pushdown(k);
        for(int i=x;i<=min(k*len,y);i++) tot+=(lon)val[i];
        for(int i=bl[x]+1;i<bl[y];i++) tot+=sum[i];
        if(bl[x]==bl[y]) return tot;
        k=bl[y];pushdown(k);
        for(int i=(k-1)*len+1;i<=y;i++) tot+=(lon)val[i];
        return tot;
    }
    
    int querymax(int x,int y){
        int maxn=-inf,k=bl[x];
        pushdown(k);
        for(int i=x;i<=min(k*len,y);i++) maxn=max(maxn,val[i]);
        for(int i=bl[x]+1;i<bl[y];i++) maxn=max(maxn,mx[i]);
        if(bl[x]==bl[y]) return maxn;
        k=bl[y];pushdown(k);
        for(int i=(k-1)*len+1;i<=y;i++) maxn=max(maxn,val[i]);
        return maxn;
    }
    
    int querymin(int x,int y){
        int minn=inf,k=bl[x];
        pushdown(k);
        for(int i=x;i<=min(k*len,y);i++)minn=min(minn,val[i]);
        for(int i=bl[x]+1;i<bl[y];i++) minn=min(minn,mn[i]);
        if(bl[x]==bl[y]) return minn;
        k=bl[y];pushdown(k);
        for(int i=(k-1)*len+1;i<=y;i++) minn=min(minn,val[i]);
        return minn;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        len=sqrt(n);
        for(int i=1;i<=n/len+1;i++){
            mx[i]=-inf;
            mn[i]=inf;
            tag2[i]=-1;
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
            bl[i]=(i-1)/len+1;
            mx[bl[i]]=max(mx[bl[i]],val[i]);
            mn[bl[i]]=min(mn[bl[i]],val[i]);
            sum[bl[i]]+=(lon)val[i];
        }
        char op[10];int x,y,z;
        for(int i=1;i<=m;i++){
            scanf("%s%d%d",op,&x,&y);
            if(op[2]=='d'||op[2]=='t') scanf("%d",&z);
            if(op[2]=='d') modify(x,y,z);
            if(op[2]=='t') change(x,y,z);
            if(op[2]=='m') printf("%lld
    ",querysum(x,y));
            if(op[2]=='x') printf("%d
    ",querymax(x,y));
            if(op[2]=='n') printf("%d
    ",querymin(x,y));
        }
        return 0;
    }
  • 相关阅读:
    Clipper库中文文档详解
    JavaScript-Clipper.js
    安装Scrapy遇到的问题
    Python中if __name__ == '__main__'的使用
    写出一段Python代码实现删除一个list里面的重复元素
    Python 内置函数(反射类)
    Python 内置函数(集合操作,IO操作)
    Python 内置函数(数学运算类,逻辑判断类)
    Python 推导式(列表推导式,字典推导式,集合推导式)
    Python 闭包和装饰器
  • 原文地址:https://www.cnblogs.com/harden/p/6486594.html
Copyright © 2011-2022 走看看