Gym - 101908C Pizza Cutter 树状数组+离散化

Grandpa Giuseppe won a professional pizza cutter, the kind of type reel and, to celebrate, baked a rectangle pizza to his grandchildren! He always sliced his pizzas into pieces by making cuts over continuous lines, not necessarily rectilinear, of two types: some begin at the left edge of the pizza, follow continuously to the right and end up in the right edge; other start on lower edge, follow continuously up and end up on the top edge. But Grandpa Giuseppe always followed a property: two cuts of the same type would never intersect. Here is an example with 4 cuts, two of each type, in the left part of the figure, which divide the pizza in 9 pieces.

It turns out that Grandpa Giuseppe simply loves geometry, topology, combinatorics and stuff; so, he decided to show to his grandchildren who could get more pieces with the same number of cuts if cross cuts of the same type were allowed. The right part of the figure shows, for example, that if the two cuts of the type that go from left to right could intercept, the pizza would be divided into 10 pieces.

Grandpa Giuseppe ruled out the property, but will not make random cuts. In addition to being one of the two types, they will comply with the following restrictions:

  • Two cuts have at most one intersection point and, if they have, it is because the cuts cross each other at that point;
  • Three cuts do not intersect in a single point;
  • Two cuts do not intersect at the border of the pizza;
  • A cut does not intercept a pizza corner.

Given the start and end points of each cut, your program should compute the number of resulting pieces from the cuts of Grandfather Giuseppe.

Input

The first line of the input contains two integers X

and Y, (1≤X,Y≤109), representing the coordinates (X,Y) of the upper-right corner of the pizza. The lower left corner has always coordinates (0,0). The second line contains two integers H and V, (1≤H,V≤105), indicating, respectively, the number of cuts ranging from left to right and the number of cuts ranging from bottom to top. Each of the following lines H contains two integers Y1 and Y2, a cut that intercepts the left side with y-coordinate Y1 and the right side at y-coordinate Y2. Each of the following V lines contains two integers X1 and X2, a cut that intercept the bottom side at x-coordinate X1 and the upper side at x-coordinate X2

.

Examples

Input

3 4
3 2
1 2
2 1
3 3
1 1
2 2

Output

13

Input

5 5
3 3
2 1
3 2
1 3
3 4
4 3
2 2

Output

19

Input

10000 10000
1 2
321 3455
10 2347
543 8765

Output

6

题意:给出一个宽为x,长为y的矩形。有一些分割线,其中h条两端点在高上,v条两端点在上下两条边上。题目保证不会有两条线的端点是同一个,也不会出现多余两条线交于一点的情况。询问最后矩形被分割成多少块。

题解: 在都没有交点的情况下有 n + m + 1 块 ,因为竖线和横线一定有交点 所以增加 n*m 个

接下来分别求横着  和  竖着  的线分别的交点个数了  一遍排序,另一边求一下逆序数就可以了,要离散化一下

#include <bits/stdc++.h>
using namespace std;
const int N=100000+10;
typedef long long ll;
#define lowbit(x) x&(-x)
struct node{
	int l,r;
}a[N];
int sum[N*2];
int n,m;
int b[N*2],cnt;
bool cmp(node x,node y)
{
	return x.l<y.l;
}
void update(int pos,int val)
{
	while(pos)
	{
		sum[pos]+=val;
		pos-=lowbit(pos);
	}
}
int query(int pos)
{
	int res=0;
	while(pos<=cnt)
	{
		res+=sum[pos];
		pos+=lowbit(pos);
	}
	return res;
}
int main()
{
	scanf("%d%d",&n,&m);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
		b[++cnt]=a[i].l;
		b[++cnt]=a[i].r;
	}
	sort(b+1,b+1+cnt);
	int len=unique(b+1,b+1+cnt)-(b+1);
	sort(a+1,a+1+n,cmp);
	ll ans=(ll)n*m+m+n+1;
	for(int i=1;i<=n;i++)
	{
		int pos=lower_bound(b+1,b+1+len,a[i].r)-b;
		ans+=query(pos);
		update(pos,1);
	}
	cnt=0;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
		b[++cnt]=a[i].l;
		b[++cnt]=a[i].r;
	}
	sort(b+1,b+1+cnt);
	len=unique(b+1,b+1+cnt)-(b+1);
	sort(a+1,a+1+m,cmp);
	memset(sum,0,sizeof(sum));
	for(int i=1;i<=m;i++)
	{
		int pos=lower_bound(b+1,b+1+len,a[i].r)-b;
		ans+=query(pos);
		update(pos,1);
	}
	printf("%lld\n",ans);
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值