XJOI网上同步训练DAY1 T2
思路:似曾相识?...见http://www.cnblogs.com/qzqzgfy/p/5266874.html
一看时限还是4s!,于是就开开心心地打了70%的分,就是用容斥原理,就可以n^3解决问题了。
实际情况:10分,wtf
我的程序:
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 const double eps=1e-6; 7 int tot[505][505],n,m,K; 8 const double Pi=acos(-1); 9 struct Point{ 10 double x,y,ang; 11 int id,bel; 12 Point(){} 13 Point(double x0,double y0):x(x0),y(y0){} 14 }d[200005],f[200005],t[200005],p[200005]; 15 struct Line{ 16 Point s,e; 17 Line(){} 18 Line(Point s0,Point e0):s(s0),e(e0){} 19 }; 20 int sgn(double x){ 21 if (x<-eps) return -1; 22 if (x>eps) return 1; 23 return 0; 24 } 25 bool cmp(Point p1,Point p2){ 26 return p1.ang<p2.ang; 27 } 28 double operator *(Point p1,Point p2){ 29 return p1.x*p2.y-p1.y*p2.x; 30 } 31 Point operator -(Point p1,Point p2){ 32 return Point(p1.x-p2.x,p1.y-p2.y); 33 } 34 int read(){ 35 char ch=getchar();int t=0,f=1; 36 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 37 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 38 return t*f; 39 } 40 bool inter(Line p1,Line p2){ 41 if (std::min(p1.s.x,p1.e.x)>std::max(p2.s.x,p2.e.x)|| 42 std::min(p1.s.y,p1.e.y)>std::max(p2.s.y,p2.e.y)|| 43 std::min(p2.s.x,p2.e.x)>std::max(p1.s.x,p1.e.x)|| 44 std::min(p2.s.y,p2.e.y)>std::max(p1.s.y,p1.e.y)) 45 return 0; 46 double a,b,c,d; 47 a=(p1.e-p1.s)*(p2.e-p1.s); 48 b=(p1.e-p1.s)*(p2.s-p1.s); 49 c=(p2.e-p2.s)*(p1.e-p2.s); 50 d=(p2.e-p2.s)*(p1.s-p2.s); 51 return (a*b<=eps)&&(c*d<=eps); 52 } 53 void sbpianfen1(){ 54 int ans=0; 55 for (int i=1;i<=n;i++) 56 for (int j=1;j<=m;j++) 57 for (int k=1;k<=K;k++) 58 for (int l=k+1;l<=K;l++) 59 if (inter(Line(d[i],f[j]),Line(t[k],t[l]))) ans++; 60 printf("%d\n",ans); 61 } 62 void updata(Point p1,Point p2,int v){ 63 if (p1.bel+p2.bel!=3) return; 64 if (p1.bel>p2.bel) std::swap(p1,p2); 65 tot[p1.id][p2.id]+=v; 66 } 67 void sbpianfen2(){ 68 for (int i=1;i<=K;i++){ 69 int cnt=0; 70 for (int j=1;j<=n;j++){ 71 p[++cnt]=d[j];p[cnt].bel=1; 72 p[cnt].ang=atan2(d[j].y-t[i].y,d[j].x-t[i].x); 73 } 74 for (int j=1;j<=m;j++){ 75 p[++cnt]=f[j];p[cnt].bel=2; 76 p[cnt].ang=atan2(f[j].y-t[i].y,f[j].x-t[i].x); 77 } 78 for (int j=1;j<=K;j++){ 79 if (j==i) continue; 80 p[++cnt]=t[j];p[cnt].bel=3; 81 p[cnt].ang=atan2(t[j].y-t[i].y,t[j].x-t[i].x); 82 } 83 std::sort(p+1,p+1+cnt,cmp); 84 for (int j=1;j<=cnt;j++){ 85 p[cnt+cnt+j]=p[cnt+j]=p[j]; 86 p[cnt+j].ang=p[j].ang+2*Pi; 87 p[cnt+cnt+j].ang=p[cnt+j].ang+2*Pi; 88 } 89 int l=1;int numl=(p[1].bel==3); 90 int numj=0,numr=0,numk=0; 91 for (int j=1;j<=cnt;j++){ 92 if (p[j].bel==3) numj++; 93 int r=j+1;numr=numj+(p[j+1].bel==3); 94 while (sgn(p[l].ang-p[j].ang-Pi)<0) l++,numl+=(p[l].bel==3); 95 for (int k=j+1,numk=numj+(p[j+1].bel==3);sgn(p[k].ang-p[j].ang-Pi)<=0;k++,numk+=(p[k].bel==3)){ 96 while (sgn(p[r+1].ang-p[k].ang-Pi)<=0) r++,numr+=(p[r].bel==3); 97 updata(p[k],p[j],numk-numj-(numr-numl+(p[l].bel==3))); 98 } 99 } 100 } 101 int ans=0; 102 for (int i=1;i<=n;i++) 103 for (int j=1;j<=m;j++) 104 ans+=tot[i][j]; 105 printf("%d\n",ans/2); 106 } 107 int main(){ 108 n=read(); 109 for (int i=1;i<=n;i++) 110 d[i].x=read(),d[i].y=read(),d[i].id=i; 111 m=read(); 112 for (int i=1;i<=m;i++) 113 f[i].x=read(),f[i].y=read(),f[i].id=i; 114 K=read(); 115 for (int i=1;i<=K;i++) 116 t[i].x=read(),t[i].y=read(),t[i].id=i; 117 if (n<=100&&m<=100&&K<=100) {sbpianfen1();return 0;} 118 if (n<=500&&m<=500&&K<=500) {sbpianfen2();return 0;} 119 }
明明应该很科学啊。。
正解:n^2做法,枚举导弹发射井,然后极角排序,统计即可。
具体做法:枚举发射井作为原点,然后将其他类型的点排序,然后一边for走过去,ans就加等于在半平面内的基地数乘以导弹防御塔数,再减去在每个基地后边的导弹防御塔数之和,注意删掉相同极角的部分,这样就是答案了,果然我数学太差了,毛都不会。。。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define ll long long 7 const double Pi=acos(-1); 8 ll ans=0; 9 int d[500005][2],n,K,m; 10 struct Point{ 11 int x,y; 12 Point(){} 13 Point(int x0,int y0):x(x0),y(y0){} 14 }S[200005],T[200005],E[200005]; 15 struct node{ 16 long double w; 17 Point p; 18 int bz; 19 }Q[500005]; 20 int read(){ 21 char ch=getchar();int t=0,f=1; 22 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 23 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 24 return t*f; 25 } 26 ll operator *(Point p1,Point p2){ 27 return (ll)p1.x*p2.y-(ll)p1.y*p2.x; 28 } 29 Point operator -(Point a,Point b){ 30 return Point(a.x-b.x,a.y-b.y); 31 } 32 bool cmp(const node a,const node b){ 33 return a.w<b.w||(!(a.p*b.p)&&a.bz<b.bz); 34 } 35 long double get(Point a){ 36 long double w=atan2(a.y,a.x); 37 if (w<0) w=w+Pi+Pi; 38 return w; 39 } 40 void calc(Point S){ 41 for (int i=1;i<=n;i++) Q[i].w=get(Q[i].p=E[i]-S),Q[i].bz=0; 42 for (int i=1;i<=K;i++) Q[i+n].w=get(Q[i+n].p=T[i]-S),Q[i+n].bz=1; 43 for (int i=1;i<=n+K;i++){ 44 Q[i+n+K]=Q[i];Q[i+n+K].w=Q[i].w+2*Pi; 45 if (Q[i].bz) Q[i+n+K].bz=2; 46 } 47 std::sort(Q+1,Q+1+n+K+n+K,cmp); 48 int sum=0,l=1,r=0,same=0; 49 ll all=0,ans1=ans; 50 for (int i=1;i<=n+K+n+K;i++){ 51 while (l<=r&&Q[d[l][0]].w+Pi<Q[i].w) all-=d[l++][1]; 52 if (Q[i].bz){ 53 if (i!=1&&Q[i].p*Q[i-1].p) same=0; 54 ans+=(ll)(r-l+1)*sum-all; 55 if (Q[i].bz==1) all+=sum-same,d[++r][0]=i,d[r][1]=sum-same; 56 }else{ 57 sum++; 58 if (i!=1&&!(Q[i].p*Q[i-1].p)) same++; 59 else same=1; 60 } 61 } 62 } 63 int main(){ 64 n=read(); 65 for (int i=1;i<=n;i++) E[i].x=read(),E[i].y=read(); 66 m=read(); 67 for (int i=1;i<=m;i++) S[i].x=read(),S[i].y=read(); 68 K=read(); 69 for (int i=1;i<=K;i++) T[i].x=read(),T[i].y=read(); 70 for (int i=1;i<=m;i++) 71 calc(S[i]); 72 printf("%lld\n",ans); 73 }