poj2761

题意:给出每只狗的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;
}
posted @ 2011-04-07 09:55  金海峰  阅读(1185)  评论(0编辑  收藏  举报