POI 2001 goldmine(没有ac)

来源:互联网 发布:徐海乔 知乎 编辑:程序博客网 时间:2024/04/29 03:20

金矿
问题描述

金矿的老师傅年底要退休了。经理为了奖赏他的尽职尽责的工作,决定在一块包含 n(n ≤ 15000) 个采金点的长方形土地中划出一块长度为 S ,宽度为 W 的区域奖励给他(1 ≤ s , w ≤ 10 000)。老师傅可以自己选择这块地的位置,显然其 中包含的采金点越多越好。你的任务就是计算最多能得到多少个采金点。如果一个采金点的位置在长方形的边上,它也应当被计算在内。

输入格式

输入文件的第一行有两个整数,中间用一个空格隔开,表示长方形土地的长和宽即s和w(1<=s,w<=10 000)。第二行有一个整数n(1<=n<=15 000),表示金矿数量。下面的n行与金矿相对应,每行两个整数x和y (-30 000<=x,y<=30 000),中间用一个空格隔开,表示金矿的坐标。

输出格式

输出文件只有一个整数,表示选择的最大金矿的数。

输入样例

1 2
12
0 0
1 1
2 2
3 3
4 5
5 5
4 2
1 4
0 5
5 0
2 3
3 2
输出样例

基本思路是,对每个矿点,确定包含该矿点的矩形的左上角范围(恰好是这个矩形本身),这样最后坐标上就是n个矩形了,找到最多相交的区域即可。这用一维线段树就可以做。

#include <cstdio>
#include <algorithm>

using namespace std;

long s, w, n;

struct tagHorzEdge
{
long ypos;
long xstart,xend;
long add;//top edge is +,bottom edge is -
void Set(long _ypos, long _xstart, long _xend, long _add)
{
ypos = _ypos;
xstart = _xstart;
xend = _xend;
add = _add;
}
bool operator < (const tagHorzEdge& the) const
{
return (ypos < the.ypos || (ypos == the.ypos && add < 0));
}
}edges[30000];

struct tagTreeNode
{
long left,right;
bool lchild;
bool rchild;
long add;
void Set(long _left, long _right, long _add)
{
left = _left;
right = _right;
lchild = rchild = false;
add = _add;
}
}segtree[1 << 17];

long ins_left,ins_right;
long maximum;
void _insert(long pos, long add)
{
//if (left,right) in ins area and is leaf node,then ins directly
tagTreeNode& node = segtree[pos];
if (ins_left <= node.left && node.right <= ins_right && !node.lchild && !node.rchild)
{
node.add += add;
if (node.add > maximum)
{
maximum = node.add;
}
return;
}

long mid = (node.left + node.right) / 2;
if (ins_right <= mid)
{
pos <<= 1;
if (!node.lchild)
{
segtree[pos].Set(node.left, mid, node.add);
node.lchild = true;
}
_insert(pos, add);
}
else if (ins_left >= mid) //insert to the right branch
{
pos <<= 1;
++pos;
if (!node.rchild)
{
segtree[pos].Set(mid + 1, node.right, node.add);
node.rchild = true;
}
_insert(pos, add);
}
else
{
pos <<= 1;
if (!node.lchild)
{
segtree[pos].Set(node.left, mid, node.add);
node.lchild = true;
}
_insert(pos, add);

++pos;
if (!node.rchild)
{
segtree[pos].Set(mid + 1, node.right, node.add);
node.rchild = true;
}
_insert(pos, add);
}
}

inline void insert(const tagHorzEdge& the)
{
ins_left = the.xstart;
ins_right = the.xend;
_insert(1, the.add);
}

int main()
{
    scanf("%d%d%d", &s, &w, &n);
long i,x,y,minx = 0x7fffffff,maxx = 0x80000000;
for (i = 0; i < n; ++i)
{
scanf("%d%d", &x, &y);
if (x < minx) minx = x;
if (x > maxx) maxx = x;
edges[i].Set(y - s, x - w, x, 1);
edges[i + n].Set(y, x - w, x, -1);
}

//sort by ypos
sort(edges, edges + 2 * n);
for (i = 0; i < 2 * n; ++i)
{
printf("%d/t[%d,/t%d]/t%c/n", edges[i].ypos, edges[i].xstart, edges[i].xend, edges[i].add > 0 ? '+' : '-');
}

//init the segment tree
maximum = 0;
segtree[1].Set(minx - w, maxx, 0);
//insert into the tree
for (i = 0; i < (n << 1); ++i)
{
insert(edges[i]);
}

//we've find the max add,output
printf("%d/n", maximum);

return 0;
}

这道题可以见于acm.cs.eunu.edu.cn。
我用求矩形周长的方法做的,现在的代码没有ac~

原创粉丝点击