USACO2014 Open Cow Optics

Cow Optics
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.

PROBLEM NAME: optics
INPUT FORMAT:

Line 1: The integers N, Bx, and By.
Lines 2..N + 1: Line i+1 describes the ith mirror with 3 elements:its (x,y) location, and its orientation (either ‘\’ or ‘/’).

SAMPLE INPUT (file optics.in):

4 1 2
-2 1 \
2 1 /
2 2 \
-2 2 /

OUTPUT FORMAT:

A single integer giving the number of locationswhere Bessie can stand to redirect the laser to the barn.

SAMPLE OUTPUT (file optics.out):

2

OUTPUT DETAILS:

A mirror at (0,1) or (0,2) placed in either direction would do the trick.

Task:奶牛们想通过镜面的反射,将位于 (0,0) ,向上发出的激光反射到位于 (Bx,By) 的家里,现在它们已经放置好了 n 面镜子,只需要放上最后一个镜子就可以将光线反射到家里。求放置此镜子的不同位置个数。
镜子只有’\‘与’/‘两种朝向,并45°放置。
Solution:
首先这光线只有竖直的和水平的。(不然这题目还能做?
然后略经思考就会发现,实际上我们从家的位置向四个方向射出光线,并从原点射出光线,它们的交点就是我们要求的答案位置。
对于这个任务来说,我们可以用竖着的线去交横着的线,用扫描线加树状数组在O(nlogn)内完成。
说实话我自己也并不是非常清晰扫描线的做法,大致就是每次在扫描线穿过一个横着的线段的右端点时把这条线段去掉,然后加上这后面的一条线段,这即将加上的点代码中即保存在putin中。
预处理略长,就是离散加将每一条线段交给一个点管理(左或下边的那个点),以及判断在不在要求的光路上。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#define M 100005
using namespace std;
struct Node{
    int x,c;//[1->/][2->\]
    bool f1,f2;
    bool operator <(const Node &a)const{
        return x<a.x;
    }
};
vector<int>X_sort,Y_sort;
int X_data[M],Y_data[M],C[M],ex,ey;
vector<Node>X[M],Y[M];
bool mark[2][M];
void draw(int x,int y,int c,int f){//[1->上][2->下][3->左][4->右]
    if(c==1||c==2){
        int t=lower_bound(Y[x].begin(),Y[x].end(),(Node){y,-1,0,0})-Y[x].begin();
        int nxt;
        if(c==1){
            nxt=t+1;
            if(f==1)Y[x][t].f1=1;
            else Y[x][t].f2=1;
            if(Y[x][nxt].c==1)draw(x,Y[x][nxt].x,4,f);
            else if(Y[x][nxt].c==2)draw(x,Y[x][nxt].x,3,f);
        }else{
            nxt=t-1;
            if(f==1)Y[x][nxt].f1=1;
            else Y[x][nxt].f2=1;
            if(Y[x][nxt].c==1)draw(x,Y[x][nxt].x,3,f);
            else if(Y[x][nxt].c==2)draw(x,Y[x][nxt].x,4,f);
        }
    }else{
        int t=lower_bound(X[y].begin(),X[y].end(),(Node){x,-1,0,0})-X[y].begin();
        int nxt;
        if(c==3){
            nxt=t-1;
            if(f==1)X[y][nxt].f1=1;
            else X[y][nxt].f2=1;
            if(X[y][nxt].c==1)draw(X[y][nxt].x,y,2,f);
            else if(X[y][nxt].c==2)draw(X[y][nxt].x,y,1,f);
        }else{
            nxt=t+1;
            if(f==1)X[y][t].f1=1;
            else X[y][t].f2=1;
            if(X[y][nxt].c==1)draw(X[y][nxt].x,y,1,f);
            else if(X[y][nxt].c==2)draw(X[y][nxt].x,y,2,f);
        }
    }
}
struct W{
    int ed,id,y;
    bool operator <(const W &a)const{
        return ed>a.ed;
    }
};
priority_queue<W>Q;
int val[M];
int lowbit(int x){
    return x&(-x);
}
void Add(int x,int d){
    while(x<=X_sort.size()+1){
        val[x]+=d;
        x+=lowbit(x);
    }
}
int Query(int x){
    int res=0;
    while(x){
        res+=val[x];
        x-=lowbit(x);
    }
    return res;
}
int main(){
    int n,sx,sy;
    scanf("%d %d %d",&n,&sx,&sy);
    for(int i=1;i<=n;i++){
        char str[5];
        scanf("%d %d %s",&X_data[i],&Y_data[i],str);
        if(str[0]=='/')C[i]=1;
        else C[i]=2;
        X_sort.push_back(X_data[i]);Y_sort.push_back(Y_data[i]);
    }
    X_sort.push_back(sx);Y_sort.push_back(sy);
    X_sort.push_back(0);Y_sort.push_back(0);
    sort(X_sort.begin(),X_sort.end());
    sort(Y_sort.begin(),Y_sort.end());
    X_sort.erase(unique(X_sort.begin(),X_sort.end()),X_sort.end());
    Y_sort.erase(unique(Y_sort.begin(),Y_sort.end()),Y_sort.end());
    for(int i=1;i<=n;i++){
        X_data[i]=lower_bound(X_sort.begin(),X_sort.end(),X_data[i])-X_sort.begin()+1;
        Y_data[i]=lower_bound(Y_sort.begin(),Y_sort.end(),Y_data[i])-Y_sort.begin()+1;
        X[Y_data[i]].push_back((Node){X_data[i],C[i],0,0});
        Y[X_data[i]].push_back((Node){Y_data[i],C[i],0,0});
    }
    sx=lower_bound(X_sort.begin(),X_sort.end(),sx)-X_sort.begin()+1;
    sy=lower_bound(Y_sort.begin(),Y_sort.end(),sy)-Y_sort.begin()+1;
    ex=lower_bound(X_sort.begin(),X_sort.end(),0)-X_sort.begin()+1;
    ey=lower_bound(Y_sort.begin(),Y_sort.end(),0)-Y_sort.begin()+1;
    X[sy].push_back((Node){sx,0,0,0});
    Y[sx].push_back((Node){sy,0,0,0});
    X[ey].push_back((Node){ex,0,0,0});
    Y[ex].push_back((Node){ey,0,0,0});
    for(int i=1;i<=X_sort.size();i++){
        Y[i].push_back((Node){0,0,0,0});
        Y[i].push_back((Node){Y_sort.size()+1,0,0,0});
        sort(Y[i].begin(),Y[i].end());
    }
    for(int i=1;i<=Y_sort.size();i++){
        X[i].push_back((Node){0,0,0,0});
        X[i].push_back((Node){X_sort.size()+1,0,0,0});
        sort(X[i].begin(),X[i].end());
    }
    draw(ex,ey,1,1);
    draw(sx,sy,1,2);draw(sx,sy,2,2);draw(sx,sy,3,2);draw(sx,sy,4,2);
/*--------------------------------<-Init-------------------------------------------*/
/*--------------------------------Calc->-------------------------------------------*/
    int ans=0;
    vector<W>putin;
    memset(val,0,sizeof(val));
    while(!Q.empty())Q.pop();
    putin.clear();
    for(int i=1;i<=Y_sort.size();i++){
        if(X[i].size()<2)continue;
        Add(i,X[i][0].f1);
        Q.push((W){X[i][1].x,0,i});
    }
    for(int i=1;i<=X_sort.size();i++){
        for(int j=0;j<putin.size();j++){
            W now=putin[j];
            Add(now.y,X[now.y][now.id+1].f1);
            Q.push((W){X[now.y][now.id+2].x,now.id+1,now.y});
        }
        putin.clear();
        while(!Q.empty()&&Q.top().ed<=i){
            W now=Q.top();
            Q.pop();
            Add(now.y,-X[now.y][now.id].f1);
            if(now.id+2<X[now.y].size())putin.push_back(now);
        }
        for(int j=0;j+1<Y[i].size();j++){
            if(!Y[i][j].f2)continue;
            ans+=Query(Y[i][j+1].x-1)-Query(Y[i][j].x);
        }
    }
/*---------------------------------------------------------------------------------*/
    memset(val,0,sizeof(val));
    while(!Q.empty())Q.pop();
    putin.clear();
    for(int i=1;i<=Y_sort.size();i++){
        if(X[i].size()<2)continue;
        Add(i,X[i][0].f2);
        Q.push((W){X[i][1].x,0,i});
    }
    for(int i=1;i<=X_sort.size();i++){
        for(int j=0;j<putin.size();j++){
            W now=putin[j];
            Add(now.y,X[now.y][now.id+1].f2);
            Q.push((W){X[now.y][now.id+2].x,now.id+1,now.y});
        }
        putin.clear();
        while(!Q.empty()&&Q.top().ed<=i){
            W now=Q.top();
            Q.pop();
            Add(now.y,-X[now.y][now.id].f2);
            if(now.id+2<X[now.y].size())putin.push_back(now);
        }
        for(int j=0;j+1<Y[i].size();j++){
            if(!Y[i][j].f1)continue;
            ans+=Query(Y[i][j+1].x-1)-Query(Y[i][j].x);
        }
    }
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值