吉司机线段树
转移自老blog
吉司机线段树
hdu5306
#define ml ((l+r)>>1) #define mr (ml+1) #define ls (rt<<1) #define rs (ls|1) int mx1[maxn<<2],num[maxn<<2],mx2[maxn<<2],lz[maxn<<2],a[maxn]; long long sum[maxn<<2]; void push_son(int son,int l,int r,int lzrt){//把最大值变为lzrt ,次大值不变 if(lzrt<mx1[son]){ sum[son]-=1ll*(mx1[son]-lzrt)*num[son]; mx1[son]=lzrt; lz[son]=lzrt; } } void push_down(int rt,int l,int r){ push_son(ls,l,ml,lz[rt]); push_son(rs,mr,r,lz[rt]); lz[rt]=0x7fffffff; } void push_up(int rt,int l,int r){ if(mx1[ls]==mx1[rs]){ mx1[rt]=mx1[ls]; num[rt]=num[ls]+num[rs]; mx2[rt]=max(mx2[ls],mx2[rs]); } else{ if(mx1[ls]>mx1[rs]){ mx1[rt]=mx1[ls]; num[rt]=num[ls]; mx2[rt]=max(mx2[ls],mx1[rs]); } else{ mx1[rt]=mx1[rs]; num[rt]=num[rs]; mx2[rt]=max(mx2[rs],mx1[ls]); } } sum[rt]=sum[ls]+sum[rs]; } void build(int rt,int l,int r){ lz[rt]=0x7fffffff; if(l==r){ mx1[rt]=a[l]; num[rt]=1; mx2[rt]=-1;// none sum[rt]=a[l]; } else{ build(ls,l,ml); build(rs,mr,r); push_up(rt,l,r); } } void update(int rt,int l,int r,int ql,int qr,int val){ if(mx1[rt]<=val) return ;//无影响 if(ql<=l&&r<=qr&&mx2[rt]<val){//只影响最大值,不影响次大值 push_son(rt,l,r,val); } else{ push_down(rt,l,r); if(ml>=ql)update(ls,l,ml,ql,qr,val); if(mr<=qr)update(rs,mr,r,ql,qr,val); push_up(rt,l,r); } } long long query_sum(int rt,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ return sum[rt]; } else{ push_down(rt,l,r); long long ret=0; if(ml>=ql) ret+=query_sum(ls,l,ml,ql,qr); if(mr<=qr) ret+=query_sum(rs,mr,r,ql,qr); return ret; } } int query_max(int rt,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ return mx1[rt]; } else{ push_down(rt,l,r); int ret=0; if(ml>=ql) ret=max(ret,query_max(ls,l,ml,ql,qr)); if(mr<=qr) ret=max(ret,query_max(rs,mr,r,ql,qr)); return ret; } }