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;      
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值