题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4376
题目大意:一个凸多边形的大蛋糕,切m刀,每刀之间不会相交(端点除外),并且不会出现切在蛋糕的边缘上,求切m刀后边最多的小蛋糕的边数.
题目思路:因为我们求的是边数,所以可以假设这块蛋糕是个正多边形,把每一刀看成线段,我们把线段从小到大排序,然后再去分蛋糕,一刀下去我们把蛋糕分成两部分,把点数少的那一部分的点去掉,因为我们线段不会相交与端点外的其他点,所以,之后切的刀一定不会切在点数少的那一部分的点上,可以自己画几个图切切看.
代码:
#include <stdlib.h> #include <string.h> #include <stdio.h> #include <ctype.h> #include <math.h> #include <time.h> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <string> #include <iostream> #include <algorithm> using namespace std; #define ull unsigned __int64 #define ll __int64 //#define ull unsigned long long //#define ll long long #define son1 New(p.xl,xm,p.yl,ym),(rt<<2)-2 #define son2 New(p.xl,xm,min(ym+1,p.yr),p.yr),(rt<<2)-1 #define son3 New(min(xm+1,p.xr),p.xr,p.yl,ym),rt<<2 #define son4 New(min(xm+1,p.xr),p.xr,min(ym+1,p.yr),p.yr),rt<<2|1 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define middle (l+r)>>1 #define MOD 1000000007 #define esp (1e-8) const int INF=0x3F3F3F3F; const double DINF=10000.00; //const double pi=acos(-1.0); const int N=10010; int n,m,tot; int nn,sum[N<<2],cov[N<<2]; struct node{ int x,y; void write(){ scanf("%d%d",&x,&y); if(x>y) swap(x,y); } bool operator < (const node& p) const { return abs(y-x-nn)>abs(p.y-p.x-nn); } }cut[N]; void PushUp(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void Build(int l,int r,int rt){ cov[rt]=0; if(l==r){sum[rt]=1;return;} int mid=middle; Build(lson),Build(rson); PushUp(rt); } void PushDown(int rt){ if(cov[rt]){ int ls=rt<<1,rs=ls|1; sum[ls]=sum[rs]=0; cov[ls]=cov[rs]=1; cov[rt]=0; } } void Update(int l,int r,int rt,int L,int R){ if(L<=l && r<=R){ sum[rt]=0,cov[rt]=1; return; } PushDown(rt); int mid=middle; if(L<=mid) Update(lson,L,R); if(mid<R) Update(rson,L,R); PushUp(rt); } int Query(int l,int r,int rt,int L,int R){ if(L<=l && r<=R) return sum[rt]; PushDown(rt); int mid=middle,ret=0; if(L<=mid) ret+=Query(lson,L,R); if(mid<R) ret+=Query(rson,L,R); return ret; } void init(){ nn=n>>1; for(int i=0;i<m;i++) cut[i].write(); sort(cut,cut+m),Build(1,n,1),tot=0; } void sof(){ for(int i=0,j,k;i<m;i++){ j=Query(1,n,1,cut[i].x,cut[i].y); k=Query(1,n,1,cut[i].y,n)+Query(1,n,1,1,cut[i].x); if(j<k) tot=max(tot,j),Update(1,n,1,cut[i].x+1,cut[i].y-1); else{ tot=max(tot,k); if(cut[i].x>1) Update(1,n,1,1,cut[i].x-1); if(cut[i].y<n) Update(1,n,1,cut[i].y+1,n); } } printf("%d\n",max(tot,sum[1])); } int main(){ //freopen("1.in","r",stdin); //freopen("1.out","w",stdout); //int T,cas;scanf("%d",&T);for(cas=1;cas<=T;cas++){ while(~scanf("%d%d",&n,&m)) init(),sof(); return 0; }