zoukankan      html  css  js  c++  java
  • HDU5306:Gorgeous Sequence——题解

    http://acm.hdu.edu.cn/showproblem.php?pid=5306

    给一个数组,m次操作:

    1:l r x,将a[i](l<=i<=r)=min(a[i],x)

    2:l r,求区间最大值。

    3:l r,求区间和。

    吉司机线段树,论文题,论文讲的很详细了。

    维护一个最大值mx和次大值se,分类讨论:

    当mx<=x显然没有影响。

    当se<x<mx打标记修改区间。

    否则暴力递归两个儿子。

    通过奇(看)技(论)淫(文)巧能够证明复杂度是O(mlogn)。

    (但是我跑得贼慢……)

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1e6+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    ll sum[N*4];
    int n,m,b[N],mx[N*4],se[N*4],lz[N*4],cnt[N*4];
    inline void upt(int a){
        int ls=a<<1,rs=a<<1|1;
        if(mx[ls]==mx[rs]){
        mx[a]=mx[ls];se[a]=max(se[ls],se[rs]);
        cnt[a]=cnt[ls]+cnt[rs];
        }
        else if(mx[ls]<mx[rs]){
        mx[a]=mx[rs];se[a]=max(mx[ls],se[rs]);
        cnt[a]=cnt[rs];
        }else{
        mx[a]=mx[ls];se[a]=max(mx[rs],se[ls]);
        cnt[a]=cnt[ls];
        }
        sum[a]=sum[ls]+sum[rs];
    }
    void build(int a,int l,int r){
        lz[a]=-1;
        if(l==r){
        sum[a]=mx[a]=b[l];
        se[a]=-1;cnt[a]=1;
        return;
        }
        int mid=(l+r)>>1;
        build(a<<1,l,mid);build(a<<1|1,mid+1,r);
        upt(a);
    }
    inline void push(int a){
        if(lz[a]==-1)return;
        int ls=a<<1,rs=a<<1|1;
        if(mx[ls]>lz[a]){
        sum[ls]-=(ll)cnt[ls]*(mx[ls]-lz[a]);
        mx[ls]=lz[a];
        lz[ls]=lz[a];
        }
        if(mx[rs]>lz[a]){
        sum[rs]-=(ll)cnt[rs]*(mx[rs]-lz[a]);
        mx[rs]=lz[a];
        lz[rs]=lz[a];
        }
        lz[a]=-1;
    }
    void mdy(int a,int l,int r,int l1,int r1,int x){
        if(r<l1||r1<l||mx[a]<=x)return;
        if(l1<=l&&r<=r1&&se[a]<x){
        sum[a]-=(ll)cnt[a]*(mx[a]-x);
        mx[a]=x;lz[a]=x;
        return;
        }
        int mid=(l+r)>>1;
        push(a);
        mdy(a<<1,l,mid,l1,r1,x);mdy(a<<1|1,mid+1,r,l1,r1,x);
        upt(a);
    }
    ll qry_sum(int a,int l,int r,int l1,int r1){
        if(r<l1||r1<l)return 0;
        if(l1<=l&&r<=r1)return sum[a];
        int mid=(l+r)>>1;
        push(a);
        return qry_sum(a<<1,l,mid,l1,r1)+qry_sum(a<<1|1,mid+1,r,l1,r1);
    }
    int qry_mx(int a,int l,int r,int l1,int r1){
        if(r<l1||r1<l)return 0;
        if(l1<=l&&r<=r1)return mx[a];
        int mid=(l+r)>>1;
        push(a);
        return max(qry_mx(a<<1,l,mid,l1,r1),qry_mx(a<<1|1,mid+1,r,l1,r1));
    }
    int main(){
        int t=read();
        while(t--){
        n=read(),m=read();
        for(int i=1;i<=n;i++)b[i]=read();
        build(1,1,n);
        while(m--){
            int op=read(),x=read(),y=read();
            if(op==0)mdy(1,1,n,x,y,read());
            if(op==1)printf("%d
    ",qry_mx(1,1,n,x,y));
            if(op==2)printf("%lld
    ",qry_sum(1,1,n,x,y));
        }
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    jmeter循环控制器
    SQL语句
    Linux防火墙常用命令
    利用cookie,实现刷新页面跳转,左侧菜单点击后状态保持不变。
    JQUERY动态生成当前年份的前5年以及后 2年
    (个人累积,分享)制作iconfont并转化图标代码使用
    如果一张要显示的图片穿插着两个路径该怎么解决?
    上传图片后台写法
    分析器错误消息:未能加载类型“XXXXXXX”
    尝试加载应用时出现了以下错误
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9154658.html
Copyright © 2011-2022 走看看