LOJ#504. 「LibreOJ β Round」ZQC 的手办 线段树+堆
由于只有取 max 标记,所以直接在线段树上维护就行.
然后取前 k 大的话就用一个堆来维护四元组 $(l,r,v,pos)$ 表示区间 $[l,r]$ 的最小值为 $v$ ,位置为 pos.
查询的时候按照 $v$ 递增的顺序取出堆顶,然后按照 pos 分裂,再扔回堆里就行了.
code:
#include <cstdio> #include <algorithm> #include <cstring> #include <queue> #define N 500009 #define lson now<<1 #define rson now<<1|1 #define inf 2000000000 #define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; int n,m; int a[N],lazy[N<<2]; struct data { int pos,v; data(int x=0,int y=inf) { pos=x,v=y; } data operator+(const data b) const { data c; if(v<b.v) { c.pos=pos,c.v=v; } else { c.pos=b.pos,c.v=b.v; } return c; } }s[N<<2]; struct node { int l,r,v,pos; node(int l=0,int r=0,int v=0,int pos=0):l(l),r(r),v(v),pos(pos){} bool operator<(const node b) const { return v>b.v; } }; priority_queue<node>q; void build(int l,int r,int now) { if(l==r) { s[now]=data(l,a[l]); return; } int mid=(l+r)>>1; build(l,mid,lson),build(mid+1,r,rson); s[now]=s[lson]+s[rson]; } void mark(int now,int v) { lazy[now]=max(lazy[now],v); s[now].v=max(s[now].v,v); } void pushdown(int now) { if(lazy[now]) { mark(lson,lazy[now]); mark(rson,lazy[now]); lazy[now]=0; } } void update(int l,int r,int now,int L,int R,int v) { if(l>=L&&r<=R) { mark(now,v); return; } int mid=(l+r)>>1; pushdown(now); if(L<=mid) update(l,mid,lson,L,R,v); if(R>mid) update(mid+1,r,rson,L,R,v); s[now]=s[lson]+s[rson]; } data query(int l,int r,int now,int L,int R) { if(l>=L&&r<=R) return s[now]; int mid=(l+r)>>1; pushdown(now); if(L<=mid&&R>mid) return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R); else if(L<=mid) return query(l,mid,lson,L,R); else return query(mid+1,r,rson,L,R); } int an[N],top; char *p1,*p2,buf[100000]; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0; char c; do { c=nc(); }while(c<48); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x; } int main() { // setIO("input"); node e; data tmp; int x,y,z,op,k; scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); build(1,n,1); scanf("%d",&m); for(int i=1;i<=m;++i) { scanf("%d",&op); if(op==1) { scanf("%d%d%d",&x,&y,&k); update(1,n,1,x,y,k); } else { scanf("%d%d%d%d",&x,&y,&z,&k); top=0; tmp=query(1,n,1,x,y); q.push(node(x,y,tmp.v,tmp.pos)); for(int j=1;j<=k;++j) { if(q.empty()) break; if(q.top().v>=z) break; e=q.top(),q.pop(); an[++top]=e.v; if(e.pos>e.l) { tmp=query(1,n,1,e.l,e.pos-1); q.push(node(e.l,e.pos-1,tmp.v,tmp.pos)); } if(e.r>e.pos) { tmp=query(1,n,1,e.pos+1,e.r); q.push(node(e.pos+1,e.r,tmp.v,tmp.pos)); } } while(!q.empty()) q.pop(); if(top==k) { for(int j=1;j<=top;++j) printf("%d ",an[j]); printf("\n"); } else printf("-1\n"); } } return 0; }