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
",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
",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
",ans); 
73 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5614422.html