• 87-区间线段树(板子)--那个苑区的人最瘦


     
    C时间限制:500 毫秒 |  C内存限制:655350 Kb
    题目内容:
    每年九月份开学的时候, 学校为了迎接新生, 食堂的伙食自然会比平时稍微好一些, 然而各个苑区食堂的伙食改善程度不尽相同.比如,南苑食堂的饭菜看起来就高大上一些, 而欣苑食堂的饭菜,emmmm, 我们还是去小吃街吃吧! 宝宝还在长身体呢,要吃好一点.
    
    这就可能导致某个苑区的学生的平均体重有所差异, 甚至差异还比较明显. 那么问题来了, 假如我现在告诉你全校所有人的体重信息,然后每次操作或者是修改编号从 x 到 y的所有人的体重, 或者是询问编号从 x 到 y 的人的平均体重, 怎么破!
    输入描述
    第一行两个正整数N,Q, 表示人数和操作次数
    接下来一行有N个正整数, 第i个数表示编号为i的人的初始体重(1<=i<=N)
    接下来有Q行, 每行或者是0 L R X 表示编号从L到R的所有人体重改变了X, 或者是1 L R 表示询问编号从L到R的人的平均体重
    (x>0表示体重增加了,x<0表示体重减小了)
    
    对于100%的数据,满足N<=10^6,Q<=10^4, 1<=L<=R<=N, -15<= x <=15
    输出描述
    对于每组询问, 输出一行一个浮点数(保留两位小数)表示编号从L到R(闭区间[L,R])的人的平均体重
    输入样例
    20 10
    97 126 124 83 81 81 92 99 108 114 96 103 103 92 101 116 112 93 123 122 1 1 12
    0 7 19 -9
    0 6 19 1
    0 5 17 9
    1 0 6
    0 6 15 -10
    1 7 12
    0 12 18 12
    1 6 7
    1 0 8
    输出样例
    100.33
    87.29
    93.00
    82.00
    86.00
    /*
     * 线段树模板
     * 区间修改 区间查询
     * 版本一:当前区间值正确,tag未下传
     */
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const int MAXN=1e6+5;
    const LL INF=2e18;
    //const int INF=0x3f3f3f3f;//根据是否超long long修改
    LL a[MAXN];
    
    //线段树节点结构体
    struct Node{
        int left,right;//左右边界
        LL mi,ma;//最小值 最大值
        LL sum;//和
        LL add;//增减标记
        int set;//重置标记
    }tree[MAXN*4];//空间开四倍
    
    //向上更新
    void PushUp(int rt){
        int lson=rt<<1,rson=rt<<1|1;   //rt << 1 | 1 等价与 rt * 2 + 1 
        tree[rt].mi=min(tree[lson].mi,tree[rson].mi);
        tree[rt].ma=max(tree[lson].ma,tree[rson].ma);
        tree[rt].sum=tree[lson].sum+tree[rson].sum;
    }
    
    //向下传递标记
    void PushDown(int rt){
        if(tree[rt].left<tree[rt].right){//如果不是叶子
            int lson=rt<<1,rson=rt<<1|1;
            if(tree[rt].set!=-1){//set初始为一个不会重置到的数,这里是-1
                tree[lson].set=tree[rt].set;tree[rson].set=tree[rt].set;
                tree[lson].add=tree[rson].add=0;//add失效
                tree[lson].mi=tree[rson].mi=tree[rt].set;
                tree[lson].ma=tree[rson].ma=tree[rt].set;
                tree[lson].sum=(LL)tree[rt].set*(tree[lson].right-tree[lson].left+1);
                tree[rson].sum=(LL)tree[rt].set*(tree[rson].right-tree[rson].left+1);
                tree[rt].set=-1;
            }
            if(tree[rt].add){
                tree[lson].add+=tree[rt].add; tree[rson].add+=tree[rt].add;
                tree[lson].mi+=tree[rt].add;  tree[rson].mi+=tree[rt].add;
                tree[lson].ma+=tree[rt].add;  tree[rson].ma+=tree[rt].add;
                tree[lson].sum+=(LL)tree[rt].add*(tree[lson].right-tree[lson].left+1);
                tree[rson].sum+=(LL)tree[rt].add*(tree[rson].right-tree[rson].left+1);
                tree[rt].add=0;
            }
        }
    }
    
    //建立函数
    void Build(int rt,int L,int R){
        tree[rt].left=L;tree[rt].right=R;tree[rt].add=0;tree[rt].set=-1;
        if(L==R) {
    		tree[rt].sum=tree[rt].mi=tree[rt].ma=a[L]; 
    		return;
    	}
        int mid=(tree[rt].left+tree[rt].right)>>1;
        Build(rt<<1,L,mid);//只有Build时LR才会变
        Build(rt<<1|1,mid+1,R);
        PushUp(rt);
    }
    
    LL QuerySum(int rt,int L,int R){
        if(R<tree[rt].left||L>tree[rt].right) return  0;
        if(L<=tree[rt].left&&tree[rt].right<=R)  
    		return tree[rt].sum;
        PushDown(rt);
        int mid=(tree[rt].left+tree[rt].right)>>1;
        LL res=0;
        if(L<=mid)  res+=QuerySum(rt<<1,L,R);
        if(R>mid)   res+=QuerySum(rt<<1|1,L,R);
        PushUp(rt);
        return  res;
    }
    
    LL QueryMin(int rt,int L,int R){
        if(L<=tree[rt].left&&tree[rt].right<=R) return tree[rt].mi;
        PushDown(rt);
        int mid=(tree[rt].left+tree[rt].right)>>1;
        LL res=INF;
        if(L<=mid) res=min(res,QueryMin(rt<<1,L,R));
        if(R>mid) res=min(res,QueryMin(rt<<1|1,L,R));
        PushUp(rt);
        return  res;
    }
    
    LL QueryMax(int rt,int L,int R){
        if(L<=tree[rt].left&&tree[rt].right<=R) return  tree[rt].ma;//完全包含才产生贡献
        PushDown(rt);
        int mid=(tree[rt].left+tree[rt].right)>>1;
        LL res=-INF;
        if(L<=mid) res=max(res,QueryMax(rt<<1,L,R));
        if(R>mid) res=max(res,QueryMax(rt<<1|1,L,R));
        PushUp(rt);
        return  res;
    }
    
    void UpdateAdd(int rt,int L,int R,int x){//把区间[L,R]加上x
        if(L<=tree[rt].left&&tree[rt].right<=R){
            tree[rt].add+=x;
            tree[rt].sum+=(LL)x*(tree[rt].right-tree[rt].left+1);
            tree[rt].mi+=x;tree[rt].ma+=x;
            return;
        }
        PushDown(rt);
        int mid=(tree[rt].left+tree[rt].right)>>1;
        if(L<=mid) UpdateAdd(rt<<1,L,R,x);
        if(R>mid) UpdateAdd(rt<<1|1,L,R,x);
        PushUp(rt);
    }
    
    void Display(int rt){
        cout<<"-------------"<<endl;
        cout<<"id: "<<rt<<endl;
        cout<<"["<<tree[rt].left<<","<<tree[rt].right<<"]"<<endl;
        cout<<"mi: "<<tree[rt].mi<<endl;
        cout<<"ma: "<<tree[rt].ma<<endl;
        cout<<"sum: "<<tree[rt].sum<<endl;
        cout<<"add: "<<tree[rt].add<<endl;
        cout<<"set: "<<tree[rt].set<<endl;
    }
    
    void bfs(int rt){
        queue<int> q;
        while(!q.empty()) q.pop();
        q.push(rt);
        while(!q.empty()){
            int fst=q.front();
            q.pop();
            Display(fst);
            if(tree[fst].right>tree[fst].left){
                q.push(fst<<1);
                q.push(fst<<1|1);
            }
        }
    }
    
    void UpdateSet(int rt,int L,int R,int x){//把区间[x,y]置为x
        if(L<=tree[rt].left&&tree[rt].right<=R){
            tree[rt].set=x;
            tree[rt].sum=(LL)x*(tree[rt].right-tree[rt].left+1);
            tree[rt].mi=x;tree[rt].ma=x;
            tree[rt].add=0;
            return;
        }
        PushDown(rt);
        int mid=(tree[rt].left+tree[rt].right)>>1;
        if(L<=mid) UpdateSet(rt<<1,L,R,x);
        if(R>mid){
            UpdateSet(rt<<1|1,L,R,x);
        }
        PushUp(rt);
    }
    
    int main(){
        int n,m;//n个数 m次询问
        while(scanf("%d%d",&n,&m)!=EOF){
            for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
            Build(1,1,n);//建立线段树
            int op,x,y,z;
            for(int i=1;i<=m;i++){
                scanf("%d%d%d",&op,&x,&y);
                if(op==1){//询问[x,y]的和,除以总数的平均
    //                printf("Case #%d:
    ",i);
                    printf("%.2lf
    ",QuerySum(1,x,y) * 1.0 / (y - x + 1));
                }
    			else if(op==2){//询问[x,y]的最大值
                    printf("Case #%d:
    ",i);
                    printf("%lld
    ",QueryMax(1,x,y));
                }
    			else if(op==3){//询问[x,y]的最小值
                    printf("Case #%d:
    ",i);
                    printf("%lld
    ",QueryMin(1,x,y));
                }
    			else if(op==0){//在[x,y]区间加上z
                    scanf("%d",&z);
                    UpdateAdd(1,x,y,z);
                }
    			else{//把[x,y]置为z
                    scanf("%d",&z);
                    UpdateSet(1,x,y,z);
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    Spring Boot 2.x基础教程:配置元数据的应用
    目前用下来最溜的MacOS微信多开工具!
    在IDEA中通过Module管理多个项目
    JAR冲突问题的解决以及运行状态下如何查看加载的类
    完美解决方案-雪花算法ID到前端之后精度丢失问题
    精讲响应式WebClient第5篇-请求超时设置与异常处理
    精讲响应式WebClient第4篇-文件上传与下载
    精讲响应式WebClient第3篇-POST、DELETE、PUT方法使用
    精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方法详解
    精讲响应式webclient第1篇-响应式非阻塞IO与基础用法
  • 原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/9540672.html
Copyright © 2020-2023  润新知