ZOJ 3511 不相交切切多边形 线段树求最大边数

九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/12070909

题意:

n多凸边形 m刀 (把n切m刀,问切完后的图形中 最多的边数 是多少)

切a点-b点

数据保证切的刀不会相交

思路:

2点之间的剩余点数就是边数,

把a-b距离 近 排序

切完一刀就统计一下切出来的蛋糕的边数,并舍弃

[a,b] 表示a,b 点间剩下的点数(就是边数)

先计算[a,b]的点数, 然后删除(a,b) 区间的点 (注意删除的是(a,b) ,所以实际操作是 删除[a,b] )

 

最后要特殊算下 剩下那块的(因为那块没有切)

 

#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<set>
#include <cstdio>  
#include <cstring>  
#include <iostream>  
#include <math.h>  
#include <queue>  
#define N 10100  
#define M 2000100  
#define inf64 0x7ffffff  
#define inf 1073741824  
#define ll int  
#define L(x) x<<1  
#define R(x) x<<1|1  
#define Mid(x,y) (x+y)>>1  
using namespace std;  
inline ll Min(ll a,ll b){return a>b?b:a;}  
inline ll Max(ll a,ll b){return a>b?a:b;}  
  
struct Point{
	int x,y,dis;

}p[N];
bool cmp(Point a,Point b){
	return a.dis<b.dis;
}
struct node{  
    int l,r;  
    ll sum;
}tree[N*4];  

void pushup(int id){
	tree[id].sum = tree[R(id)].sum + tree[L(id)].sum;
}

void build(int l,int r,int id){
	tree[id].l = l, tree[id].r = r;
	tree[id].sum = r - l + 1;
	if(l == r)return ;
	int mid = Mid(l,r);
	build( l, mid, L(id));		
	build( mid+1, r, R(id));

}

void updata(int l, int r,int id){
	if(l == tree[id].l && tree[id].r == r)
	{ tree[id].sum = 0; return ;}

	int mid=Mid(tree[id].l, tree[id].r);
	if(r <= mid)updata(l, r, L(id));
	else if(mid < l) updata(l, r, R(id));
	else 
	{
		updata(l, mid, L(id));
		updata(mid+1, r, R(id));
	}
	pushup(id);
}
int query(int l, int r, int id){
	if(tree[id].sum==0)return 0;
	if( tree[id].l == tree[id].r)return tree[id].sum;
	int mid=Mid(tree[id].l, tree[id].r);

	if(r <= mid)
		return query(l, r, L(id));
	if(mid < l )
		return query(l, r, R(id));

	return query(l, mid, L(id)) + query(mid+1, r, R(id));
}

int main(){
	int n, m, i,temp;
	while(~scanf("%d %d",&n,&m)){

		for(i=1;i<=m;i++){
			scanf("%d %d",&p[i].x,&p[i].y);
			if(p[i].x>p[i].y)
				temp=p[i].x, p[i].x=p[i].y, p[i].y=temp;
			p[i].dis=p[i].y-p[i].x;
		}

		sort(p+1, p+m+1, cmp);

		build(1,n,1);

		int ans=0;
		for(i=1;i<=m;i++){

			ans=Max(ans, query(p[i].x, p[i].y, 1));
			updata(p[i].x+1, p[i].y-1, 1);

		}
		ans=Max(ans, query(1,n,1));
		printf("%d\n",ans);

	}
	return 0;
}

/*
6 3
1 5
1 4
1 3

ans:
3
*/

你可能感兴趣的:(ZOJ 3511 不相交切切多边形 线段树求最大边数)