【好题】思维+几何+离散化——ICPC PNWRC 2019 G

这题的投影求交解法很新奇

/*
把脉冲i往后推ti个单位,然后将其投影在y=x上
把所有投影点按x坐标排序,遇到垂直脉冲投影的起点,cntv++,遇到垂直脉冲投影的终点,cntv-- 
遇到水平脉冲投影的起点,ans+=cntv
垂直脉冲的贡献同理 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 200005

typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){
    if (k>eps) return 1; else if (k<-eps) return -1; return 0;
}
int cmp(db k1,db k2){return sign(k1-k2);}
int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}
struct point{
    db x,y;
    int v,h,s,e;
    point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
    point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
    point operator * (db k1) const{return (point){x*k1,y*k1};}
    point operator / (db k1) const{return (point){x/k1,y/k1};}
    int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
    point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
    point turn90(){return (point){-y,x};}
    db abs(){return sqrt(x*x+y*y);}
    db abs2(){return x*x+y*y;}
    db dis(point k1){return ((*this)-k1).abs();}
    point unit(){db w=abs(); return (point){x/w,y/w};}
};
int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影 
    point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2());
}

int comp(point a,point b){
    return a.x<b.x;
}
point k1,k2,k3,v[N<<2]; 
int n,m;

int main(){
    k1=(point){0.0,0.0};
    k2=(point){1.0,1.0};
    cin>>n;
    for(int i=1;i<=n;i++){
        char ch;int t,mm,a;//后推距离,长度,坐标 
        scanf("
%c
",&ch);
        cin>>t>>mm>>a;
        if(ch=='h'){//水平的 
            k3=(point){-t*1.0,a*1.0}; 
            point k4=proj(k1,k2,k3);
            k4.h=1;k4.e=1; 
            v[++m]=k4;
            
            k3=(point){-t*1.0-mm+eps,a*1.0};
            k4=proj(k1,k2,k3);
            k4.h=1;k4.s=1;
            v[++m]=k4;
        } 
        else {//垂直的 
            k3=(point){a*1.0,-t*1.0}; 
            point k4=proj(k1,k2,k3);
            k4.v=1;k4.e=1;
            v[++m]=k4;
            
            k3=(point){a*1.0,-t*1.0-mm+eps}; 
            k4=proj(k1,k2,k3);
            k4.v=1;k4.s=1;
            v[++m]=k4;
        }
    }
    sort(v+1,v+1+m,comp);
    
    long long ans=0,cnth=0,cntv=0;
    for(int i=1;i<=m;i++){
        if(v[i].h && v[i].s){
            ans+=cntv;cnth++;
        }else if(v[i].h && v[i].e){
            cnth--;
        }else if(v[i].v && v[i].s){
            ans+=cnth;cntv++;
        }else {
            cntv--;
        }
    }
    cout<<ans<<'
';
} 
原文地址:https://www.cnblogs.com/zsben991126/p/12843553.html