LibreOJ504

来源:互联网 发布:h5制作软件下载 编辑:程序博客网 时间:2024/06/15 14:02

ZQC 的手办

题目链接

分类:线段树、堆

1.题意概述

  • 给你一个序列a[1…n],有两种操作:
    • 1 l r k:表示把区间[l,r]中小于k的数都改成k
    • 2 l r k x:表示从小到大输出在区间[l,r]中小于k的数的前x个,如果不足则输出-1
  • 数据范围:
    • 1n5×105:表示序列长度
    • 1m5×105:表示操作次数
    • 1ai1091k1091x105

2.解题思路

  • 用一棵线段树维护区间最小值及其位置,这个可以在单次O(logn)时间内维护。
    每次查询时,用一个堆查询区间最小的x个值,具体做法是:用一个四元组(l,r,p,v)表示区间[l,r]内,p这个位置的值最小,值为v,以v作为比较的关键字维护一个最小堆。初始时把整个询问区间的查询结果放入堆中,然后重复以下操作x次:

    • 取出堆顶元素并加入答案——这个答案肯定是前x小的
    • 如果lp,把[l,p1]的查询结果加入堆中
    • 如果rp,把[p+1,r]的查询结果加入堆中

    如果vx或者区间元素不足,则输出1,否则按顺序输出即可!

  • 复杂度分析

    • 时间复杂度:O[(n+x)logn]
    • 空间复杂度:O(n)

3.AC代码

#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define maxn 500010#define lson root << 1#define rson root << 1 | 1#define lent (t[root].r - t[root].l + 1)#define lenl (t[lson].r - t[lson].l + 1)#define lenr (t[rson].r - t[rson].l + 1)#define N 1111#define eps 1e-6#define pi acos(-1.0)#define e exp(1.0)#define Close() ios::sync_with_stdio(0),cin.tie(0)using namespace std;const int mod = 1e9 + 7;typedef long long ll;typedef unsigned long long ull;int a[maxn];struct tree{    int l, r, val, tag, pos;} t[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; }    friend bool operator< (const data &x, const data &y)    {        return x.v > y.v;    }};priority_queue<data> q;vector<int> ans;void pushup(int root){    if (t[lson].val < t[rson].val)    {        t[root].val = t[lson].val;        t[root].pos = t[lson].pos;    }    else    {        t[root].val = t[rson].val;        t[root].pos = t[rson].pos;    }}void pushdown(int root){    if (!t[root].tag || t[root].l == t[root].r)        return;    t[lson].val = max(t[lson].val, t[root].tag);    t[rson].val = max(t[rson].val, t[root].tag);    t[lson].tag = t[rson].tag = t[root].tag;    t[root].tag = 0;}void build(int l, int r, int root){    t[root].l = l;    t[root].r = r;    t[root].tag = 0;    if (l == r)    {        t[root].pos = l;        t[root].val = a[l];        return;    }    int mid = l + r >> 1;    build(l, mid, lson);    build(mid + 1, r, rson);    pushup(root);}void update(int l, int r, int k, int root){    if (l <= t[root].l && t[root].r <= r)    {        if (t[root].val < k)            t[root].val = k;        t[root].tag = k;        return;    }    pushdown(root);    int mid = t[root].l + t[root].r >> 1;    if (l <= mid)        update(l, r, k, lson);    if (r > mid)        update(l, r, k, rson);    pushup(root);}pair<int, int> query(int l, int r, int root){    if (l <= t[root].l && t[root].r <= r)        return make_pair(t[root].val, t[root].pos);    pushdown(root);    int mid = t[root].l + t[root].r >> 1;    pair<int, int> res = make_pair(1e9, 0);    if (l <= mid)        res = min(res, query(l, r, lson));    if (r > mid)        res = min(res, query(l, r, rson));    return res;}int main(){#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin);    freopen("out.txt", "w", stdout);    long _begin_time = clock();#endif    int n, m;    scanf("%d", &n);    for (int i = 1; i <= n; i++)        scanf("%d", &a[i]);    build(1, n, 1);    scanf("%d", &m);    while (m--)    {        int op, l, r, k, x;        scanf("%d%d%d%d", &op, &l, &r, &k);        if (op == 1)            update(l, r, k, 1);        else        {            scanf("%d", &x);            if (r - l + 1 < x)            {                puts("-1");                continue;            }            while (!q.empty())                q.pop();            ans.clear();            pair<int, int> u = query(l, r, 1);            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)                {                    pair<int, int> w = query(u.l, u.pos - 1, 1);                    q.push(data(u.l, u.pos - 1, w.first, w.second));                }                if (u.r > u.pos)                {                    pair<int, int> w = query(u.pos + 1, u.r, 1);                    q.push(data(u.pos + 1, u.r, w.first, w.second));                }            }            int sz = ans.size();            if (sz < x)                puts("-1");            else            {                for (int i = 0; i < sz; i++)                    if (i == 0)                        printf("%d", ans[i]);                    else                        printf(" %d", ans[i]);                puts("");            }        }    }#ifndef ONLINE_JUDGE    long _end_time = clock();    printf("time = %ld ms.", _end_time - _begin_time);#endif    return 0;}