zoj 3511 Cake Robbery

zju 3511 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3511

 

ZOJ Problem Set - 3511
Cake Robbery

Time Limit: 2 Seconds      Memory Limit: 65536 KB

As usual, Alice finishes her delicious cake at noon. Unfortunately, the smell of cake beckoned hungry Bob, and he decided to rob one piece of cake.

The cake is a convex polygon with N edges. At the beginning, Bob cut it along the diagonals. AfterM cuts, Bob decided to rob the 'largest' piece of cake. Strangely, in Bob's opinion, the piece has the most number of edge is the biggest one.

Please help Bob to find the 'largest' piece.

Input

There are multiple test cases (about 20).

The first line of each test case contains two integer number N, M (5 <=N <= 10000), indicating the number of point of the cake and the cut, respectively.

The following M lines contain two integer x, y (1 <= x, y <=N), denoting the index of the starting and ending cut point. (the index of points mark from 1 toN clockwise.)

The input will guarantee that all of the cuts will not intersect inside the cake, but they may cross each other at the edge of cake, and Bob won't cut along the initial edge of the cake.

Output

Output the maximal size (most number of edges) of the piece which Bob will get.

Sample Input
7 2
3 6
7 2
Sample Output
4

 

 

 

 

题意:

  按顶点标号(1--n)顺时针给出1个凸多边形

然后给出m组 切蛋糕的方法[x,y] 表示x,y两点之间切一刀

数据保证刀法不交叉 问切完后最多边数的小蛋糕有多少条边

 

我的做法是先切出边数最少的蛋糕 然后依次切边数多的

由于多边形的边数等于顶点数

边数就可以根据 |y-x| 的大小来判断 |y-x| 小的边数自然小了

先切边数少的 就先对y-x进行从小到大排序

 

这里切完一条边时 记录当前切出蛋糕的边数 (也就是[x,y]闭区间中顶点个数)  与最大值进行比较

 

然后删除(x,y)这个开区间 

这里用查询点数和删除操作用区间树处理

 注意切完所以刀最后还要统计依次[1--n]中的点数 画个图看看吧

举例:

先切[3 5]  计算出三角形345边数为3 然后删除4这个点 再切[3 6]  计算出三角形356的边数3  删除5  最后计算1 2 3 6 有四个边

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
#define MAXN 10010

struct IM
{
	int l,r;
	int node;
};
struct INN
{
	int x,y;
}oper[MAXN];

IM segtree[MAXN*4];

void swap(int &x,int &y)
{
	int t=x;
	x=y;
	y=t;
}

int cmp(const INN &a,const INN &b)
{
	return a.y-a.x<b.y-b.x;
}

void Settree(int l,int r,int i)
{
	segtree[i].l=l;
	segtree[i].r=r;
	segtree[i].node=r-l+1;
	if(l==r)
		return;
	int m=(l+r)>>1;
	Settree(l,m,i<<1);
	Settree(m+1,r,i<<1|1);
}

int Query(int l,int r,int i)
{
	if(segtree[i].node==0)
		return 0;
	if(segtree[i].l==segtree[i].r)
		return segtree[i].node;
	int m=(segtree[i].l+segtree[i].r)>>1;
	if(r<=m)
		return Query(l,r,i<<1);
	else
	if(l>m)
		return Query(l,r,i<<1|1);
	else
		return Query(l,m,i<<1)+Query(m+1,r,i<<1|1);
}
void Treecut(int l,int r,int i)
{
	if(segtree[i].l==l && segtree[i].r==r)
	{
		segtree[i].node=0;
		return;
	}
	int a,b,mid;
	a=i<<1;
	b=a|1;
	mid=(segtree[i].l+segtree[i].r)>>1;
	if(r<=mid)
		Treecut(l,r,a);
	else
	if(l>mid)
		Treecut(l,r,b);
	else
	{
		Treecut(l,mid,a);
		Treecut(mid+1,r,b);
	}
	segtree[i].node=segtree[a].node+segtree[b].node;
}
int main()
{
	int n,m,i;
	while(~scanf("%d %d",&n,&m))
	{
		for(i=0;i<m;i++)
		{
			scanf("%d %d",&oper[i].x,&oper[i].y);
			if(oper[i].x>oper[i].y)
				swap(oper[i].x,oper[i].y);
		}

		sort(oper,oper+m,cmp);

		Settree(1,n,1);

		int maxv;
		int ans=0;
		for(i=0;i<m;i++)
		{
			maxv=Query(oper[i].x,oper[i].y,1);
			if(ans<maxv)
				ans=maxv;
			Treecut(oper[i].x+1,oper[i].y-1,1);
		}
		maxv=Query(1,n,1);
		if(ans<maxv)
			ans=maxv;
		printf("%d\n",ans);
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值