JSOI2014第三轮 DAY2T2 士兵部署
2014-12-10 20:20
141 查看
// 完全搞不懂版权到底是个什么东西..不过如果内容侵犯版权的话请提醒我删除=A=
题目大意:
给你若n个士兵,对于一个点,如果从该点出发,朝任意一个方向移动,都会和至少一个士兵的距离减少,则称这个点是可以被守卫的。可以守卫的区域,就是所有这样的点的集合。
然后有m个询问,每个询问输入一个士兵坐标,问你如果加入该士兵,守卫的区域面积是多大。
对于30%的数据满足n,m≤500;
对于60%的数据满足n,m≤10000,并且至多只有500个位置满足部署新士兵之后,可以守卫的区域的面积会增加;
对于100%的数据满足n,m≤10^5,−10^8≤Xi,Yi,Ui,Vi≤10^8。
因为版权问题担惊受怕啊。。目前只写出了60分的。
很显然。守卫面积就是凸包面积。首先,我们维护出一个凸包。然后对于每个询问,二分求出士兵的位置以及士兵是否在一开始的凸包内部。
如果不在则从二分出的位置开始向两边枚举。用差积算出增加的面积。【这里复杂度是O(n)的】
然后就好了。。60分get√
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
脑补出AC的方法了。。在凸包内取一个点。对于每次加入都可以logn二分出连到这个点面积增加的最左和最右。然后就三角形面积-凸包内部面积就是答案了。
改到200多行还是wa....估计今天是出不来了
/*结果竟然一周都没怎么写程序。。然后就不想写这题了。总之思路是对的...不过实现还是有细节*/
题目大意:
给你若n个士兵,对于一个点,如果从该点出发,朝任意一个方向移动,都会和至少一个士兵的距离减少,则称这个点是可以被守卫的。可以守卫的区域,就是所有这样的点的集合。
然后有m个询问,每个询问输入一个士兵坐标,问你如果加入该士兵,守卫的区域面积是多大。
对于30%的数据满足n,m≤500;
对于60%的数据满足n,m≤10000,并且至多只有500个位置满足部署新士兵之后,可以守卫的区域的面积会增加;
对于100%的数据满足n,m≤10^5,−10^8≤Xi,Yi,Ui,Vi≤10^8。
因为版权问题担惊受怕啊。。目前只写出了60分的。
很显然。守卫面积就是凸包面积。首先,我们维护出一个凸包。然后对于每个询问,二分求出士兵的位置以及士兵是否在一开始的凸包内部。
如果不在则从二分出的位置开始向两边枚举。用差积算出增加的面积。【这里复杂度是O(n)的】
然后就好了。。60分get√
#include<cmath> #include<cstdio> #include<algorithm> using namespace std; struct points { double x,y; }a[100011],chs[100011]; inline double max(double x,double y) { if(x>y) return x; return y; } inline double xabs(double x) { if(x<0) x=-x; return x; } inline double dis(points x,points y) { return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y)); } inline double multi(points p0, points p1, points p2) { return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } inline bool cmp(points x,points y) { if(multi(x,y,a[1])>0) return true; if(multi(x,y,a[1])==0&&dis(x,a[1])<dis(y,a[1])) return true; return false; } int main() { freopen("soldier.in","r",stdin); freopen("soldier.out","w",stdout); int n,m; scanf("%d%d",&n,&m); int i; for(i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y); double minx=2100000000,miny=2100000000; int d=0; for(i=1;i<=n;i++) { if(a[i].y<miny) { minx=a[i].x; miny=a[i].y; d=i; } else if(a[i].y==miny) { if(a[i].x<minx) { minx=a[i].x; d=i; } } } points t; t=a[d]; a[d]=a[1]; a[1]=t; sort(a+2,a+1+n,cmp); int sp=1,k=2; chs[0]=a ; chs[1]=a[1]; while(k<=n) { double x=multi(chs[sp],chs[sp-1],a[k]); if(x<=0) { sp++; chs[sp]=a[k]; k++; } else sp--; } double ans=0; for(i=2;i<=sp-1;i++) ans+=xabs(multi(chs[1],chs[i],chs[i+1])); //printf("%.1lf\n",ans/double(2)); double x,y; chs[sp+1]=chs[1]; for(i=1;i<=m;i++) { scanf("%lf%lf",&x,&y); int l=2,r=sp+1,mid; points po; po.x=x; po.y=y; bool flag=false; while(l<=r) { mid=(l+r)/2; double tx,ty; tx=multi(chs[mid+1],chs[1],po); ty=multi(chs[mid],chs[1],po); if(tx<=0&&ty<=0) l=mid+1; else if(tx>0&&ty<=0) { flag=true; break; } else r=mid-1; } if(flag) { bool ff=false; double exans=ans; if(chs[mid+1].x>chs[mid].x) { double k=(chs[mid+1].y-chs[mid].y)/(chs[mid+1].x-chs[mid].x); double xt=chs[mid].y-chs[mid].x*k; if(po.y-po.x*k>xt&&a[1].y-a[1].x*k<=xt||po.y-po.x*k<=xt&&a[1].y-a[1].x*k>xt) { ff=true; exans+=xabs(multi(chs[mid+1],chs[mid],po)); } } else if(chs[mid+1].x==chs[mid].x) { if(po.x>chs[mid].x&&a[1].x<=chs[mid].x||po.x<=chs[mid].x&&a[1].x>chs[mid].x) { ff=true; exans+=xabs(multi(chs[mid+1],chs[mid],po)); } } else { double k=(chs[mid].y-chs[mid+1].y)/(chs[mid].x-chs[mid+1].x); double xt=chs[mid].y-chs[mid].x*k; if(po.y-po.x*k>xt) { ff=true; exans+=xabs(multi(chs[mid+1],chs[mid],po)); } } if(ff) { int ll=mid,rr=mid+1; while(multi(chs[ll],chs[ll-1],po)>0&&ll>1) { exans+=xabs(multi(chs[ll],chs[ll-1],po)); ll--; } while(multi(chs[rr],chs[rr+1],po)<0&&rr<sp) { exans+=xabs(multi(chs[rr+1],chs[rr],po)); rr++; } } printf("%.1lf\n",exans/double(2)); } else { double exans=ans; int ll=sp,rr=2; if(multi(chs[2],chs[1],po)>0) { exans+=xabs(multi(chs[2],chs[1],po)); //while(multi(chs[rr],chs[1],po)<multi(chs[rr+1],chs[1],chs[rr])&&rr<sp) while(multi(chs[rr],chs[rr+1],po)<0&&rr<sp) { exans+=xabs(multi(chs[rr+1],chs[rr],po)); rr++; } } if(multi(chs[sp],chs[1],po)<0) { exans+=xabs(multi(chs[sp],chs[1],po)); //while(multi(chs[ll],chs[1],po)>multi(chs[ll-1],chs[1],chs[ll])&&ll>2) while(multi(chs[ll],chs[ll-1],po)>0&&ll>1) { exans+=xabs(multi(chs[ll],chs[ll-1],po)); ll--; } } printf("%.1lf\n",exans/double(2)); } } return 0; }
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
脑补出AC的方法了。。在凸包内取一个点。对于每次加入都可以logn二分出连到这个点面积增加的最左和最右。然后就三角形面积-凸包内部面积就是答案了。
改到200多行还是wa....估计今天是出不来了
/*结果竟然一周都没怎么写程序。。然后就不想写这题了。总之思路是对的...不过实现还是有细节*/
相关文章推荐
- jzoj3865[JSOI2014]士兵部署
- [jzoj3865/JSOI2014]士兵部署
- 【JSOI2014】【JZOJ 3861】支线剧情2
- 【JSOI 2014】序列维护
- BZOJ 3875: [Ahoi2014&Jsoi2014]骑士游戏 dp spfa
- ,Myeclipse 2014 部署项目 无jar包问题
- Myeclipse打包部署到Weblogic(Myeclipse2014+Weblogic10.3)
- SQL Server 2014 日志传送部署:总览
- Myeclipse2014中,新建部署Maven项目
- [bzoj5039][Jsoi2014]序列维护 线段树
- BZOJ3876 [Ahoi2014&Jsoi2014]支线剧情
- 【JSOI2014】歌剧表演
- BZOJ5039: [Jsoi2014]序列维护
- 使用Advanced Installer 13.7进行AutoCAD2012(2014)插件打包 一(配置文件部署)
- Myeclipse2014中,新建部署Maven项目
- bzoj3876 [Ahoi2014&Jsoi2014]支线剧情(有源汇有上下界最小费用流)
- 3876: [Ahoi2014&Jsoi2014]支线剧情
- 【JSOI2014】支线剧情
- 【bzoj5037】[Jsoi2014]电信网络 最大权闭合图
- JZOJ5537.【2014东莞市选】【JSOI2014】病毒分类