Loj 504 ZQC的手办

Loj 504 ZQC的手办

  • 用线段树维护,每个节点存储区间内最小值 \(val\) 以及最小值出现的一个位置 \(pos\) .
  • 对操作 \(1\) ,只需打标记即可,因为我们不维护其他的信息(如区间和),只对最小值修改,容易完成.
  • 对操作 \(2\) ,用一个四元组 \((l,r,v,pos)\)\(v\) 形成的小根堆来查询区间前 \(x\) 小的值,每次取出堆顶,加入答案,再不断对线段树询问 \(p\) 两侧的 \((val,pos)\),插入堆中,重复做 \(x\) 次即可.注意特判元素不足或堆顶 \(v\geq x\) 的无解情况.
  • 总时间复杂度为 \(O(logn\cdot (n+\sum x))\).

    以前好像做过一道类似的题?总之用线段树同时维护最小值即其位置是一种经典的套路做法.

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
#define root Tree[o]
#define lson Tree[o<<1]
#define rson Tree[o<<1|1]
#define inf (1e9)+7
inline int read()
{
    int x=0;
    bool pos=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')
            pos=0;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-'0';
    return pos?x:-x;
}
const int MAXN=5e5+10;
int n,m;
struct node{
    int l,r;
    int val,pos;
    int tag;
    node()
        {
            tag=0;
        }
}Tree[MAXN<<2];
struct data{
    int l,r,v,pos;
    data(int x,int y,int c,int d)
        {
            l=x,r=y,v=c,pos=d;
        }
    bool operator < (const data &rhs) const
        {
            return v>rhs.v;
        }
};
priority_queue<data> q;
vector<int> ans;
int a[MAXN];
void pushup(int o)
{
    if(lson.val<rson.val)
        root.pos=lson.pos;
    else
        root.pos=rson.pos;
    root.val=min(lson.val,rson.val);
}
void Modifiy(int o,int v)
{
    root.val=max(root.val,v);
    root.tag=v;
}
void pushdown(int o)
{
    if(root.tag)
        {
            Modifiy(o<<1,root.tag);
            Modifiy(o<<1|1,root.tag);
            root.tag=0;
        }
}
void BuildTree(int o,int l,int r)
{
    root.l=l,root.r=r;
    if(l==r)
        {
            root.pos=l;
            root.val=a[l];
            return;
        }
    int mid=(l+r)>>1;
    BuildTree(o<<1,l,mid);
    BuildTree(o<<1|1,mid+1,r);
    pushup(o);
}
void update(int o,int L,int R,int k)
{
    int l=root.l,r=root.r;
    if(l>R || r<L)
        return;
    if(L<=l && r<=R)
        {
            Modifiy(o,k);
            return;
        }
    pushdown(o);
    int mid=(l+r)>>1;
    if(L<=mid)
        update(o<<1,L,R,k);
    if(R>mid)
        update(o<<1|1,L,R,k);
    pushup(o);
}
pii query(int o,int L,int R)//min,pos
{
    int l=root.l,r=root.r;
    pii res=mp(inf,-1);
    if(l>R || r<L)
        return res;
    if(L<=l && r<=R)
        return mp(root.val,root.pos);
    pushdown(o);
    int mid=(l+r)>>1;
    if(L<=mid)
        res=min(res,query(o<<1,L,R));
    if(R>mid)
        res=min(res,query(o<<1|1,L,R));
    return res;
}
int main()
{
    n=read();
    for(int i=1;i<=n;++i)
        a[i]=read();
    BuildTree(1,1,n);
    m=read();
    while(m--)
        {
            int op=read(),l=read(),r=read(),k=read();
            if(op==1)
                update(1,l,r,k);
            else
                {
                    int x=read();
                    if(r-l+1<x)
                        {
                            puts("-1");
                            continue;
                        }
                    while(!q.empty())
                        q.pop();
                    ans.clear();
                    pii u=query(1,l,r);
                    q.push(data(l,r,u.first,u.second));
                    for(int i=1;i<=x;++i)
                        {
                            data u=q.top();
                            q.pop();
                            if(u.v<k)
                                ans.push_back(u.v);
                            else
                                break;
                            if(u.l<u.pos)
                                {
                                    pii w=query(1,u.l,u.pos-1);
                                    q.push(data(u.l,u.pos-1,w.first,w.second));
                                }
                            if(u.r>u.pos)
                                {
                                    pii w=query(1,u.pos+1,u.r);
                                    q.push(data(u.pos+1,u.r,w.first,w.second));
                                }
                        }
                    int siz=ans.size();
                    if(siz<x)
                        puts("-1");
                    else
                        {
                            for(int i=0;i<siz;++i)
                                printf("%d ",ans[i]);
                            puts("");
                        }
                }
        }
    return 0;
}

转载于:https://www.cnblogs.com/jklover/p/10397556.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值