1. 程式人生 > >【HDU5306】Gorgeous Sequence

【HDU5306】Gorgeous Sequence

處理 def printf pan 第一題 get pushd logs max

這個題目是Segment-Tree-beats的論文的第一題。

首先我們考慮下這個問題的不同之處在於,有一個區間對x取max的操作。

那麽如何維護這個操作呢?

就是對於線段樹的區間,維護一個最大值標記,最大值出現次數,以及嚴格次大值。

接下來考慮處理操作。

首先如果x>maxv[o]證明已經是無所謂的,所以應該直接放棄。

如果v處於semx[o]<x<maxv[o],證明只有最大值需要被修改。

其他的情況就繼續向下遞進就可以了。

那麽我們證明一下為什麽這麽做復雜度是對的。

首先,如同論文中所說的,對於每個maxv可以看作是一個標記,把相同的maxv合並到第一個點,

可以發現semx的含義就是子樹中最大的maxv。(因為最大值已經被縮到了這個點上)

每次暴力進入這些節點的時候,實際上就是將標記進行合並。

(也就是文章中所說的標記回收的理論)

這個題的難點就是為什麽我這麽暴力的回收依然可以是一個log的。

在每一次操作後會產生一類新的標記。

那麽每次標記回收實際上就是有一類標記的權值-=1

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e6+5;
int a[N],n,m;
struct Segment_Tree{
#define lson (o<<1)
#define rson (o<<1|1)
    int
maxv[N<<2],cntv[N<<2],semx[N<<2]; ll sumv[N<<2]; inline void pushup(int o){ sumv[o]=sumv[lson]+sumv[rson]; maxv[o]=max(maxv[lson],maxv[rson]); semx[o]=max(semx[lson],semx[rson]);cntv[o]=0; if(maxv[lson]!=maxv[rson])semx[o]=max(semx[o],min(maxv[lson],maxv[rson]));
if(maxv[o]==maxv[lson])cntv[o]+=cntv[lson]; if(maxv[o]==maxv[rson])cntv[o]+=cntv[rson]; } inline void puttag(int o,int v){ if(v>=maxv[o])return; sumv[o]+=1LL*(v-maxv[o])*cntv[o];maxv[o]=v; } inline void pushdown(int o){puttag(lson,maxv[o]);puttag(rson,maxv[o]);} inline void build(int o,int l,int r){ if(l==r){ sumv[o]=maxv[o]=a[l];cntv[o]=1;semx[o]=-1; return; } int mid=(l+r)>>1; build(lson,l,mid);build(rson,mid+1,r); pushup(o); } inline void optmax(int o,int l,int r,int ql,int qr,int v){ if(v>=maxv[o])return; if(ql<=l&&r<=qr&&v>semx[o]){puttag(o,v);return;} int mid=(l+r)>>1;pushdown(o); if(ql<=mid)optmax(lson,l,mid,ql,qr,v); if(qr>mid)optmax(rson,mid+1,r,ql,qr,v); pushup(o); } inline ll querysum(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return sumv[o]; int mid=(l+r)>>1;pushdown(o);ll ans=0; if(ql<=mid)ans+=querysum(lson,l,mid,ql,qr); if(qr>mid)ans+=querysum(rson,mid+1,r,ql,qr); return ans; } inline int querymax(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return maxv[o]; pushdown(o);int mid=(l+r)>>1,ans=-1; if(ql<=mid)ans=max(ans,querymax(lson,l,mid,ql,qr)); if(qr>mid)ans=max(ans,querymax(rson,mid+1,r,ql,qr)); return ans; } }sgt; inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch==-)f=-1;}while(ch<0||ch>9); do{x=x*10+ch-0;ch=getchar();}while(ch>=0&&ch<=9); return f*x; } int main(){ int T=read(); while(T--){ n=read();m=read(); for(int i=1;i<=n;i++)a[i]=read(); sgt.build(1,1,n); while(m--){ int opt=read(),l=read(),r=read(); if(opt==0){ int v=read(); sgt.optmax(1,1,n,l,r,v); } if(opt==1)printf("%d\n",sgt.querymax(1,1,n,l,r)); if(opt==2)printf("%lld\n",sgt.querysum(1,1,n,l,r)); } } }

【HDU5306】Gorgeous Sequence