题目链接
分类:线段树、堆
用一棵线段树维护区间最小值及其位置,这个可以在单次 O(logn) 时间内维护。
每次查询时,用一个堆查询区间最小的 x 个值,具体做法是:用一个四元组 (l,r,p,v) 表示区间 [l,r] 内, p 这个位置的值最小,值为 v ,以 v 作为比较的关键字维护一个最小堆。初始时把整个询问区间的查询结果放入堆中,然后重复以下操作 x 次:
如果 v≥x 或者区间元素不足,则输出 −1 ,否则按顺序输出即可!
复杂度分析:
#include
#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 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;
}