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/+
+++++++++++++++++++++++++++++++++++++++++++