题解 P5545 【[JSOI2016]炸弹攻击2】
xtx1092515503 · · 题解
Portal
直接统计显然是不行的(
我们考虑符合条件的三元组个数。显然,因为激光塔全在
但需要注意的是,当激光塔对与该射线无交点时,这个三元组是不合法的;稍加观察即可发现,有交点的充要条件是两激光塔的向量夹角
于是我们考虑再固定一个激光塔
在 two-pointers 的过程中,我们可以记录以当前节点为端点时的答案
当一个激光塔进入区间时,
时间复杂度
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double pi=acos(-1);
int E,T,B;
ll res;
struct Vector{
int x,y;
Vector(int X=0,int Y=0){x=X,y=Y;}
friend Vector operator +(const Vector &u,const Vector &v){return Vector(u.x+v.x,u.y+v.y);}
friend Vector operator -(const Vector &u,const Vector &v){return Vector(u.x-v.x,u.y-v.y);}
friend Vector operator *(const Vector &u,const int &v){return Vector(u.x*v,u.y*v);}
friend Vector operator /(const Vector &u,const int &v){return Vector(u.x/v,u.y/v);}
friend ll operator &(const Vector &u,const Vector &v){return 1ll*u.x*v.y-1ll*u.y*v.x;}//cross times
friend ll operator |(const Vector &u,const Vector &v){return 1ll*u.x*v.x+1ll*u.y*v.y;}//point times
double operator !()const{return atan2(y,x);}
friend bool operator <(const Vector &u,const Vector &v){return !u<!v;}
void read(){scanf("%d%d",&x,&y);}
void print(){printf("(%d,%d)",x,y);}
}ene[810],tow[810],bea[810];
pair<Vector,bool>p[1610];
int main(){
scanf("%d",&E);
for(int i=1;i<=E;i++)ene[i].read();
scanf("%d",&B);
for(int i=1;i<=B;i++)bea[i].read();
scanf("%d",&T);
for(int i=1;i<=T;i++)tow[i].read();
for(int o=1;o<=B;o++){
int m=0;
for(int i=1;i<=T;i++)p[m++]=make_pair(tow[i]-bea[o],0);
for(int i=1;i<=E;i++)p[m++]=make_pair(ene[i]-bea[o],1);
sort(p,p+m);
int sum=0,se=0,st=0,len=0;
for(int j=0,k=0;j<m;){
while(len<m&&(p[j].first&p[k].first)>=0){
if(p[k].second==1)se++;
else sum+=se,st++;
len++,k=(k+1)%m;
}
if(p[j].second==0)res+=sum;
if(p[j].second==0)st--;
else sum-=st,se--;
j++,len--;
}
}
printf("%lld\n",res);
return 0;
}