题意:给出每只狗的pretty value,然后多次询问,每次输出区间[i,j](狗站成一排,从第i只到第j只)的第k小的值是多少。区间之间有交叉,但是没有完全包含。
分析:先把所有区间排序,然后从左至右把每个区间用线段树维护离散化后的pretty value,即线段树的区间的意义是pretty value。每次删除在上一个区间中且不在当前区间中的节点,插入在当前区间中且不在上一个区间中的节点,使得线段树中的节点恰好为该区间内的所有节点。然后查询第k个就容易了。
View Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
usingnamespace std;
#define maxn 100005
#define maxm 50005
struct Interval
{
int s, e, k, pos, ans;
}interval[maxm];
struct Node
{
Node *pleft, *pright;
int l, r;
int num;
}tree[maxn *3];
int dog[maxn], n, m, pretty[maxn], opdog[maxn], ncount;
booloperator< (const Interval &a, const Interval &b)
{
if (a.s != b.s)
return a.s < b.s;
return a.e < b.e;
}
bool cmp(const Interval &a, const Interval &b)
{
return a.pos < b.pos;
}
int binarysearch(int a)
{
int l =0;
int r = n -1;
int mid = (l + r) /2;
while (l < r)
{
if (pretty[mid] < a)
l = mid +1;
else
r = mid;
mid = (l + r) /2;
}
return l;
}
void buildtree(Node *proot, int l, int r)
{
proot->l = l;
proot->r = r;
proot->num =0;
if (l == r)
return;
int mid = (l + r) /2;
ncount++;
proot->pleft = tree + ncount;
ncount++;
proot->pright = tree + ncount;
buildtree(proot->pleft, l, mid);
buildtree(proot->pright, mid +1, r);
}
void ins(Node *proot, int a, int d)
{
proot->num += d;
if (proot->l == proot->r)
return;
int mid = (proot->l + proot->r) /2;
if (a <= mid)
ins(proot->pleft, a, d);
else
ins(proot->pright, a, d);
}
int query(Node *proot, int k)
{
if (proot->l == proot->r)
return pretty[proot->l];
if (proot->pleft->num >= k)
return query(proot->pleft, k);
else
return query(proot->pright, k - proot->pleft->num);
}
void input()
{
scanf("%d%d", &n, &m);
for (int i =0; i < n; i++)
{
scanf("%d", &dog[i]);
pretty[i] = dog[i];
}
for (int i =0; i < m ; i++)
{
scanf("%d%d%d", &interval[i].s, &interval[i].e, &interval[i].k);
interval[i].s--;
interval[i].e--;
interval[i].pos = i;
}
}
void work()
{
for (int i = interval[0].s; i <= interval[0].e; i++)
ins(tree, dog[i], 1);
interval[0].ans = query(tree, interval[0].k);
for (int i =1; i < m; i++)
{
for (int j = interval[i -1].s; j <= min(interval[i -1].e, interval[i].s -1); j++)
ins(tree, dog[j], -1);
for (int j = max(interval[i -1].e +1, interval[i].s); j <= interval[i].e; j++)
ins(tree, dog[j], 1);
interval[i].ans = query(tree, interval[i].k);
}
}
int main()
{
//freopen("D:\\t.txt", "r", stdin);
input();
sort(interval, interval + m);
sort(pretty, pretty + n);
for (int i =0; i < n; i++)
{
dog[i] = binarysearch(dog[i]);
opdog[dog[i]] = i;
}
ncount =0;
buildtree(tree, 0, n -1);
work();
sort(interval, interval + m, cmp);
for (int i =0; i < m; i++)
printf("%d\n", interval[i].ans);
return0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
usingnamespace std;
#define maxn 100005
#define maxm 50005
struct Interval
{
int s, e, k, pos, ans;
}interval[maxm];
struct Node
{
Node *pleft, *pright;
int l, r;
int num;
}tree[maxn *3];
int dog[maxn], n, m, pretty[maxn], opdog[maxn], ncount;
booloperator< (const Interval &a, const Interval &b)
{
if (a.s != b.s)
return a.s < b.s;
return a.e < b.e;
}
bool cmp(const Interval &a, const Interval &b)
{
return a.pos < b.pos;
}
int binarysearch(int a)
{
int l =0;
int r = n -1;
int mid = (l + r) /2;
while (l < r)
{
if (pretty[mid] < a)
l = mid +1;
else
r = mid;
mid = (l + r) /2;
}
return l;
}
void buildtree(Node *proot, int l, int r)
{
proot->l = l;
proot->r = r;
proot->num =0;
if (l == r)
return;
int mid = (l + r) /2;
ncount++;
proot->pleft = tree + ncount;
ncount++;
proot->pright = tree + ncount;
buildtree(proot->pleft, l, mid);
buildtree(proot->pright, mid +1, r);
}
void ins(Node *proot, int a, int d)
{
proot->num += d;
if (proot->l == proot->r)
return;
int mid = (proot->l + proot->r) /2;
if (a <= mid)
ins(proot->pleft, a, d);
else
ins(proot->pright, a, d);
}
int query(Node *proot, int k)
{
if (proot->l == proot->r)
return pretty[proot->l];
if (proot->pleft->num >= k)
return query(proot->pleft, k);
else
return query(proot->pright, k - proot->pleft->num);
}
void input()
{
scanf("%d%d", &n, &m);
for (int i =0; i < n; i++)
{
scanf("%d", &dog[i]);
pretty[i] = dog[i];
}
for (int i =0; i < m ; i++)
{
scanf("%d%d%d", &interval[i].s, &interval[i].e, &interval[i].k);
interval[i].s--;
interval[i].e--;
interval[i].pos = i;
}
}
void work()
{
for (int i = interval[0].s; i <= interval[0].e; i++)
ins(tree, dog[i], 1);
interval[0].ans = query(tree, interval[0].k);
for (int i =1; i < m; i++)
{
for (int j = interval[i -1].s; j <= min(interval[i -1].e, interval[i].s -1); j++)
ins(tree, dog[j], -1);
for (int j = max(interval[i -1].e +1, interval[i].s); j <= interval[i].e; j++)
ins(tree, dog[j], 1);
interval[i].ans = query(tree, interval[i].k);
}
}
int main()
{
//freopen("D:\\t.txt", "r", stdin);
input();
sort(interval, interval + m);
sort(pretty, pretty + n);
for (int i =0; i < n; i++)
{
dog[i] = binarysearch(dog[i]);
opdog[dog[i]] = i;
}
ncount =0;
buildtree(tree, 0, n -1);
work();
sort(interval, interval + m, cmp);
for (int i =0; i < m; i++)
printf("%d\n", interval[i].ans);
return0;
}