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\n",qry_mx(1,1,n,x,y));
        if(op==2)printf("%lld\n",qry_sum(1,1,n,x,y));
    }
    }
    return 0;
}

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

 +本文作者:luyouqi233。               +

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

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

posted @ 2018-06-08 11:14  luyouqi233  阅读(257)  评论(0编辑  收藏  举报