3356: [Usaco2004 Jan]禁闭围栏
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 45 Solved: 26
[ Submit][ Status][ Discuss]
Description
贝茜又做犯事了,约翰打算关她禁闭.他的农场建有N(1≤N≤250000)个矩形篱笆.围栏不重叠也互不接触,但足一个围栏可能包含一个或几个其他的围栏.他知道贝茜擅长逃脱,所以希望把她放在一个被围的层数最多的围栏里.请为他找出这样的围栏,并求出有多少个这样的围栏
Input
第1行:一个整数N.
第2到N+1行:每行四个整数X1,Y1,X2,Y2,表示围栏的左下角和右上角.X,y∈[1..10^9],
且X1<X2,Y1< Y2
Output
两个整数:最大层数和几个这样的围栏.
Sample Input
4
1 1 16 16
6 6 11 13
7 7 9 12
3 3 10 5
Sample Output
3 1
先将y坐标离散化,然后从左往右扫描,每遇到一条正方形的边就更新树状数组
正方形处理如下:
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef struct Line
{
int x, l, r, id, t;
bool operator < (const Line &b) const
{
if(x<b.x)
return 1;
return 0;
}
}Line;
Line s[500005];
int cnt, p[500005], tre[500005], sum[500005];
int Query(int k)
{
int ans = 0;
while(k)
{
ans += tre[k];
k -= k&-k;
}
return ans;
}
void Update(int k, int x)
{
while(k<=cnt)
{
tre[k] += x;
k += k&-k;
}
}
int main(void)
{
int x1, y1, x2, y2, n, i, bet, ans;
scanf("%d", &n);
for(i=1;i<=n;i++)
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
p[++cnt] = y1, s[cnt].id = i, s[cnt].t = 1, s[cnt].l = y1, s[cnt].r = y2, s[cnt].x = x1;
p[++cnt] = y2, s[cnt].id = i, s[cnt].t = -1, s[cnt].l = y1, s[cnt].r = y2, s[cnt].x = x2;
}
sort(p+1, p+cnt+1);
cnt = unique(p+1, p+cnt+1)-(p+1);
n *= 2;
sort(s+1, s+n+1);
for(i=1;i<=n;i++)
{
s[i].l = lower_bound(p+1, p+cnt+1, s[i].l)-p;
s[i].r = lower_bound(p+1, p+cnt+1, s[i].r)-p;
}
for(i=1;i<=n;i++)
{
if(s[i].t==1)
sum[s[i].id] = Query(s[i].l)+1;
Update(s[i].l, s[i].t);
Update(s[i].r, -s[i].t);
}
n /= 2;
ans = 0, bet = 0;
for(i=1;i<=n;i++)
{
if(sum[i]==bet)
ans++;
else if(sum[i]>bet)
bet = sum[i], ans = 1;
}
printf("%d %d\n", bet, ans);
return 0;
}