USACO2014Open Gold Cow Optics

来源:互联网 发布:淘宝上的代理可靠吗 编辑:程序博客网 时间:2024/06/05 01:10

Task:
Farmer John’s cows would like to host a dance party in their barn, complete
with a laser light show. Unfortunately, the only working laser they have
found is located far away from the barn and too heavy to move, so they plan
to re-direct the laser light to the barn using a series of mirrors.
The layout of the farm has the laser at position (0,0) pointing north (in
the positive y direction), and the barn at (Bx, By); we can think of both
the laser and the barn as points in the 2D plane. There are already N cows
(1 <= N <= 100,000) scattered throughout the farm holding mirrors that are
aligned at angles of 45 degrees to the axes. For example, a mirror aligned
like \ will take a beam of light entering from below and reflect it to the
left. We can also think of the mirrors as being located at points in the
2D plane.
Just before pressing the big red button to activate the laser, Bessie
noticed a major flaw in the plan: the laser cannot hit the barn with the
mirrors in their current configuration! As a result, she plans to run out
onto the field, and hold up one more mirror (placed once again at a 45
degree angle) in order to redirect the laser onto the barn. Please count
the number of locations in the field where Bessie can stand to accomplish
this goal.
All coordinates are integers between -1,000,000,000 and 1,000,000,000. It
is guaranteed that any mirrors to be placed will be in this range as well.
The cows running the laser insist that the beam should never come back to
(0,0) after leaving this location (and with the mirrors in their initial
configuration, it is guaranteed that this will not happen). No two cows
occupy the same point in space, and Bessie cannot locate herself at the
same position as an existing cow.

SAMPLE INPUT
4 1 2
-2 1 \
2 1 /
2 2 \
-2 2 /

SAMPLE OUTPUT
2

Solution:
一道不算太难的题目吧.
我们先离散一下,然后将按Y轴存一张图,按X轴存一下图,再预处理出从(0,0)向上出发,会经过那些边,以及从(Bx,By)出发,会经过哪些边.

那么我们可以知道,如果一条(0,0)出发的能到达的边与从(Bx,By)出发能到达的边有交点,那么在交点放一面镜子,我们就能够使光线到达农场.

如图所示(别吐槽画图技术):
这里写图片描述

那么在处理完这个之后,我们就可以开始去算这些东西了.

首先很明了的就是O(n2logn)的去算,枚举每条边,然后去一一判断与它相交的边能否满足.

我们先去枚举那些竖着的从(Bx,By)可以到达的边,然后去把每条横着的边放到堆里面去,并按照其到期时间排序,然后出来的时候要在下一次算的时候才能放进去新的,所以我们创立一个putin来存这些,然后之前存进去的东西可以用一个树状数组来算,存[1,X]被从(0,0)出发能到的边的个数,然后每条边加一下就好了.

以及为了方便,在预处理的时候打了个表.

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<queue>#define M 100005#define Right 1#define Left 2#define Up 3#define Down 4using namespace std;int X[M],Y[M],n,Bx,By,Ox,Oy;//1 Right 2 Left 3 Up 4 Down //1 / 2 \ //int turned[10][10]={    {0,0,0},    {0,3,4},    {0,4,3},    {0,1,2},    {0,2,1},};//从di的方向,经过了mi的镜子,返回之后的方向  struct W{    int pos,mi;    bool sol1,sol2;//sol1为从(0,0)出发,能否到达, sol2为从(Bx,By)出发     bool operator <(const W &a)const{        return pos<a.pos;    }};struct T{    int x,y,mi;}Q[M];vector<W>Xm[M],Ym[M];void dfs(int x,int y,int f,int t){    if(f==Up){        int nxy=lower_bound(Xm[x].begin(),Xm[x].end(),(W){y,0,0,0})-Xm[x].begin();        if(t==1)Xm[x][nxy].sol1=1;        else Xm[x][nxy].sol2=1;        if(Xm[x][nxy+1].mi!=0)dfs(x,Xm[x][nxy+1].pos,turned[f][Xm[x][nxy+1].mi],t);    }else if(f==Down){        int nxy=lower_bound(Xm[x].begin(),Xm[x].end(),(W){y,0,0,0})-Xm[x].begin();        if(t==1)Xm[x][nxy-1].sol1=1;        else Xm[x][nxy-1].sol2=1;        if(Xm[x][nxy-1].mi!=0)dfs(x,Xm[x][nxy-1].pos,turned[f][Xm[x][nxy-1].mi],t);    }else if(f==Left){        int nxx=lower_bound(Ym[y].begin(),Ym[y].end(),(W){x,0,0,0})-Ym[y].begin();        if(t==1)Ym[y][nxx-1].sol1=1;        else Ym[y][nxx-1].sol2=1;        if(Ym[y][nxx-1].mi!=0)dfs(Ym[y][nxx-1].pos,y,turned[f][Ym[y][nxx-1].mi],t);    }else {        int nxx=lower_bound(Ym[y].begin(),Ym[y].end(),(W){x,0,0,0})-Ym[y].begin();        if(t==1)Ym[y][nxx].sol1=1;        else Ym[y][nxx].sol2=1;        if(Ym[y][nxx+1].mi!=0)dfs(Ym[y][nxx+1].pos,y,turned[f][Ym[y][nxx+1].mi],t);    }}int Tree[M],sx=0,sy=0;void Add(int x,int v){    while(x<=sx+1){        Tree[x]+=v;        x+=(x)&(-x);    }}int Sum(int x){    int re=0;    while(x){        re+=Tree[x];        x-=(x)&(-x);    }    return re;}struct G{    int End,id,y;    bool operator <(const G &a)const{        return End>a.End;    }};priority_queue<G>q;vector<G>putin;int main(){    Ox=Oy=0;    scanf("%d %d %d",&n,&Bx,&By);    X[sx++]=0,X[sx++]=Bx;    Y[sy++]=0,Y[sy++]=By;    for(int i=1;i<=n;i++){        char P[10];        scanf("%d %d %s",&Q[i].x,&Q[i].y,P);        Q[i].mi=(P[0]!='/')+1;        X[sx++]=Q[i].x;        Y[sy++]=Q[i].y;    }    sort(X,X+sx);sort(Y,Y+sy);    sx=unique(X,X+sx)-X,sy=unique(Y,Y+sy)-Y;    for(int i=1;i<=n;i++){        Q[i].x=lower_bound(X,X+sx,Q[i].x)-X+1;        Q[i].y=lower_bound(Y,Y+sy,Q[i].y)-Y+1;        Xm[Q[i].x].push_back((W){Q[i].y,Q[i].mi,0,0});        Ym[Q[i].y].push_back((W){Q[i].x,Q[i].mi,0,0});    }    Ox=lower_bound(X,X+sx,Ox)-X+1;    Oy=lower_bound(Y,Y+sy,Oy)-Y+1;    Bx=lower_bound(X,X+sx,Bx)-X+1;    By=lower_bound(Y,Y+sy,By)-Y+1;    Xm[Ox].push_back((W){Oy,0,0,0});    Ym[Oy].push_back((W){Ox,0,0,0});    Xm[Bx].push_back((W){By,0,0,0});    Ym[By].push_back((W){Bx,0,0,0});    for(int i=1;i<=sx;i++){        Xm[i].push_back((W){0,0,0,0});        Xm[i].push_back((W){sy+1,0,0,0});        sort(Xm[i].begin(),Xm[i].end());    }    for(int i=1;i<=sy;i++){        Ym[i].push_back((W){0,0,0,0});        Ym[i].push_back((W){sx+1,0,0,0});        sort(Ym[i].begin(),Ym[i].end());    }    dfs(Ox,Oy,Up,1);    for(int i=1;i<=4;i++)dfs(Bx,By,i,2);    int ans=0;    memset(Tree,0,sizeof(Tree));    while(!q.empty())q.pop();    for(int i=1;i<=sy;i++){        if(Ym[i].size()<2)continue;        Add(i,Ym[i][0].sol1);        q.push((G){Ym[i][1].pos,0,i});    }    for(int i=1;i<=sx;i++){        int up=putin.size();        for(int j=0;j<up;j++){            G now=putin[j];            Add(now.y,Ym[now.y][now.id+1].sol1);            q.push((G){Ym[now.y][now.id+2].pos,now.id+1,now.y});        }        putin.clear();        while(!q.empty()&&q.top().End<=i){            G now=q.top();q.pop();            int nowy=now.y;            Add(nowy,-Ym[nowy][now.id].sol1);            if(now.id<Ym[nowy].size()-2)putin.push_back(now);        }        up=Xm[i].size()-1;        for(int j=0;j<up;j++){            if(!Xm[i][j].sol2)continue;            int L=Xm[i][j].pos+1,R=Xm[i][j+1].pos-1;            ans+=Sum(R)-Sum(L-1);        }    }    memset(Tree,0,sizeof(Tree));    while(!q.empty())q.pop();    putin.clear();    for(int i=1;i<=sy;i++){        if(Ym[i].size()<2)continue;        Add(i,Ym[i][0].sol2);        q.push((G){Ym[i][1].pos,0,i});    }    for(int i=1;i<=sx;i++){        int up=putin.size();        for(int j=0;j<up;j++){            G now=putin[j];            Add(now.y,Ym[now.y][now.id+1].sol2);            q.push((G){Ym[now.y][now.id+2].pos,now.id+1,now.y});        }        putin.clear();        while(!q.empty()&&q.top().End<=i){            G now=q.top();q.pop();            int nowy=now.y;            Add(nowy,-Ym[nowy][now.id].sol2);            if(now.id<Ym[nowy].size()-2)putin.push_back(now);        }        up=Xm[i].size()-1;        for(int j=0;j<up;j++){            if(!Xm[i][j].sol1)continue;            int L=Xm[i][j].pos+1,R=Xm[i][j+1].pos-1;            ans+=Sum(R)-Sum(L-1);        }    }    printf("%d\n",ans);    return 0;}
0 0