题解
对于区间取(max),这个比较好办,直接在线段树上打标记就行了。
如果让我们弹出前(n)个数,我们可以用类似超级钢琴的思想,队列中每个元素是一个线段树节点,弹出时记录最值的位置,然后分成两半继续做就行了。
代码
#include<bits/stdc++.h>
#define N 500009
using namespace std;
typedef long long ll;
int n,a[N],m;
int tr[N<<2],pos[N<<2],la[N<<2];
int ans[N],top;
bool tag[N<<2];
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
struct node{
int nw,l,r;
inline bool operator <(const node &b)const{
return tr[nw]>tr[b.nw];
}
};
priority_queue<node>q;
inline void pushup(int cnt){
tr[cnt]=tr[cnt<<1];pos[cnt]=pos[cnt<<1];
if(tr[cnt<<1|1]<tr[cnt])tr[cnt]=tr[cnt<<1|1],pos[cnt]=pos[cnt<<1|1];
}
inline void pushdown(int cnt){
la[cnt<<1]=max(la[cnt<<1],la[cnt]);
la[cnt<<1|1]=max(la[cnt<<1|1],la[cnt]);
tr[cnt<<1]=max(tr[cnt<<1],la[cnt]);
tr[cnt<<1|1]=max(tr[cnt<<1|1],la[cnt]);
la[cnt]=0;
}
void build(int cnt,int l,int r){
if(l==r){
pos[cnt]=l;
tr[cnt]=a[l];
tag[cnt]=1;
return;
}
int mid=(l+r)>>1;
build(cnt<<1,l,mid);
build(cnt<<1|1,mid+1,r);
pushup(cnt);
}
void upd(int cnt,int l,int r,int L,int R,int x){
if(l>=L&&r<=R){
tr[cnt]=max(tr[cnt],x);
la[cnt]=max(la[cnt],x);
return;
}
int mid=(l+r)>>1;
if(la[cnt])pushdown(cnt);
if(mid>=L)upd(cnt<<1,l,mid,L,R,x);
if(mid<R)upd(cnt<<1|1,mid+1,r,L,R,x);
pushup(cnt);
}
void query(int cnt,int l,int r,int L,int R){
if(l>=L&&r<=R){
q.push(node{cnt,l,r});
return;
}
int mid=(l+r)>>1;
if(la[cnt])pushdown(cnt);
if(mid>=L)query(cnt<<1,l,mid,L,R);
if(mid<R)query(cnt<<1|1,mid+1,r,L,R);
}
int main(){
n=rd();
for(int i=1;i<=n;++i)a[i]=rd();
build(1,1,n);
m=rd();
int opt,l,r,k,x;
while(m--){
opt=rd();l=rd();r=rd();k=rd();
if(opt==1){
upd(1,1,n,l,r,k);
}
else{
x=rd();
while(!q.empty())q.pop();
query(1,1,n,l,r);
for(int i=1;i<=x;++i){
if(q.empty())break;
int cnt=q.top().nw;
node y=q.top();q.pop();
if(tr[cnt]>=k)break;
ans[++top]=tr[cnt];
if(tag[cnt])continue;
pushdown(cnt);
if(y.l<=pos[cnt]-1)query(cnt,y.l,y.r,y.l,pos[cnt]-1);
if(pos[cnt]+1<=y.r)query(cnt,y.l,y.r,pos[cnt]+1,y.r);
}
if(top==x){for(int i=1;i<=top;++i)printf("%d ",ans[i]);puts("");}
else puts("-1");
top=0;
}
}
return 0;
}