LOJ504 ZQC的手办--线段树最值及位置+优先队列

 

#include <bits/stdc++.h>
using namespace std;
#define inf 1000000007
typedef pair<int,int>pii;
const int maxn = 500000+10;
int n,m;
int w[maxn];
vector<int>ans;

inline int read() {   //输入挂
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}

struct ad{
	int l,r,v,pos;
    ad(int x,int y,int z,int p)//构造函数
        {
            l=x,r=y,v=z,pos=p;
        }
    bool operator < (const ad &r1) const  //变为小根堆
        {
            return v>r1.v;
        }
};
priority_queue<ad> que;

/*-------------------------线段树------------------------------*/
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int pos[maxn<<2],maxv[maxn<<2],lazy[maxn<<2];
void pushup(int rt)
{
	if(maxv[rt<<1]<maxv[rt<<1|1]){
		pos[rt]=pos[rt<<1];
	}
	else pos[rt]=pos[rt<<1|1];
    maxv[rt] =min(maxv[rt<<1],maxv[rt<<1|1]);
}

void pushdown(int rt,int l,int r)
{
    if(lazy[rt])
    {
        maxv[rt<<1]=max(maxv[rt<<1],lazy[rt]);
        maxv[rt<<1|1]=max(maxv[rt<<1|1],lazy[rt]);
        lazy[rt<<1] = (lazy[rt]);
        lazy[rt<<1|1] = (lazy[rt]);
		lazy[rt] = 0;
    }
}

void build(int l,int r,int rt)
{
    if(l==r)
    {
    	pos[rt]=l;
        maxv[rt] = w[l];
        return ;
    }
    int m = l+r>>1;
    build(lson);
    build(rson);
    pushup(rt);
}



void change(int val,int q,int l,int r,int rt)//单点更新 
{
    if(l==r)
    {
        pos[rt]=l;
        maxv[rt]=val;
        return ;
    }
    int m = l + r >> 1;
    if(q<=m)
        change(val,q,lson);
    else
        change(val,q,rson);
    pushup(rt);
}

void update(int L,int R,int val,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
    	maxv[rt]=max(maxv[rt],val);
    	lazy[rt]=val;
        return ;
    }
    int m = l + r >> 1;
    pushdown(rt,m-l+1,r-m);
    if(L<=m)
        update(L,R,val,lson);
    if(R>m)
        update(L,R,val,rson);
    pushup(rt);
}

pii query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
        return make_pair(maxv[rt],pos[rt]);
    int m = l + r >> 1;
	pii ans=make_pair(inf,-1);
	  pushdown(rt,m-l+1,r-m);
    if (L<=m)ans=min(ans,query(L,R,lson));
    if (R>m)ans=min(ans,query(L,R,rson));

    return ans;
}


/*-------------------------线段树------------------------------*/
int main()
{
  n=read();//scanf("%d",&n);
  for(int i=1;i<=n;i++)w[i]=read();
  build(1,n,1);
  m=read();
  while(m--){
  	int op,l,r,k,x;
  	op=read();
	  l=read();
	  r=read();
	  k=read(); 
  	//scanf("%d%d%d%d",&op,&l,&r,&k);
  	
  	if(op==1)update(l,r,k,1,n,1);
  	else{
  		x=read();
		  if(r-l+1<x)printf("-1\n");//区间不够长 
		  else{
		  	while(!que.empty()){
		  		que.pop();
			  }
			  ans.clear();
		  	pii st=query(l,r,1,n,1);
		  	que.push(ad(l,r,st.first,st.second));
		  	for(int i=1;i<=x;i++){
		  		ad tmp=que.top();
		  		que.pop();
		  		if(tmp.v<k)
		  		ans.push_back(tmp.v);//每次放一个最小值
		  		else break;
		  		if(tmp.l<tmp.pos){//去掉最值找 
		  			pii tmp2=query(tmp.l,tmp.pos-1,1,n,1);
		  			que.push(ad(tmp.l,tmp.pos-1,tmp2.first,tmp2.second));
				  }
				  if(tmp.r>tmp.pos){
		  			pii tmp2=query(tmp.pos+1,tmp.r,1,n,1);
		  			que.push(ad(tmp.pos+1,tmp.r,tmp2.first,tmp2.second));
				  }
			  }
			  int s=ans.size();
			  if(s<x)printf("-1\n");
			  else{
			  	for(int i=0;i<s;i++){
			  		if(i!=s-1)printf("%d ",ans[i]);
			  		else printf("%d\n",ans[i]);
				  }
			  	
			  }
		  }
		  
	  } 
  }
  return 0;
  
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值