Guest User

hide and seek

a guest
Aug 18th, 2014
1,336
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.18 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <set>
  4. #include <utility>
  5. #include <cmath>
  6. #include <queue>
  7. #include <functional>
  8. #include <algorithm>
  9.  
  10. #define PI 1.157079632679
  11. #define EPS 1e-7
  12.  
  13. using namespace std;
  14. typedef long long ll;
  15.  
  16. struct point{
  17.     ll x, y;
  18.     point(){}
  19.     point (int _x, int _y){x = _x; y = _y;}
  20.     bool operator==(point other) const{ return x == other.x && y == other.y; }
  21.     point operator+(point other) const{ return point(x+other.x, y+other.y); }
  22.     point operator-(point other) const{ return point(x-other.x, y-other.y); }
  23. };
  24.  
  25. point ax(1,0), ay(0,1);
  26.  
  27. point seeker;
  28.  
  29. typedef point vec;
  30.  
  31. inline vec toVec(point a, point b){ return vec(b.x - a.x, b.y - a.y);}
  32.  
  33. inline ll cross(vec a, vec b){ return a.x*b.y - b.x*a.y; }
  34.  
  35. inline bool ccw(point o, point a, point b){ return cross(toVec(o,a),toVec(o,b)) > 0; }
  36.  
  37.  
  38. // using this before sorting by cross vector operation -> guarantees transitivity property needed for sorting(if a > b, b> c then c > a)
  39. // returns quadrant of a point A wrt rotation center O
  40. inline int quadrant(point o, point a){
  41.     point a1 = a-o;
  42.     if(a1.x > 0 && a1.y >= 0) return 0;
  43.     if(a1.x <= 0 && a1.y > 0) return 1;
  44.     if(a1.x < 0 && a1.y <= 0) return 2;
  45.     if(a1.x >= 0 && a1.y < 0) return 3;
  46.     return 0;
  47. }
  48.  
  49. #define LINE_TYPE   0
  50. #define KID_TYPE    1
  51. #define LINE_BEGIN  0
  52. #define LINE_END    1
  53.  
  54. struct evt{
  55.     point p;
  56.     int type, id;
  57.     bool inicio;
  58.      
  59.     evt(){}
  60.     evt(point _p, int _id, int _type, bool _inicio){ p = _p; id = _id; type = _type; inicio = _inicio;}
  61.     bool operator>(evt lhs) const{
  62.         int qR = quadrant(seeker, p),
  63.             qL = quadrant(seeker, lhs.p);
  64.  
  65.         if(qR > qL) return true;
  66.         if(qR < qL) return false;
  67.          
  68.         if(ccw(seeker, lhs.p, p)) return true;
  69.         if(ccw(seeker, p, lhs.p)) return false;
  70.          
  71.         if(type == LINE_TYPE && lhs.type == KID_TYPE){
  72.             if(inicio == LINE_BEGIN) return false;
  73.             if(inicio == LINE_END)   return true;
  74.         }
  75.          
  76.         if(type == KID_TYPE && lhs.type == LINE_TYPE){
  77.             if(lhs.inicio == LINE_BEGIN) return true;
  78.             if(lhs.inicio == LINE_END)   return false;
  79.         }
  80.          
  81.         if(type == LINE_TYPE && lhs.type == LINE_TYPE){
  82.             if(inicio == LINE_BEGIN) return false;
  83.             else                     return true;
  84.              
  85.         }
  86.          
  87.         return true;
  88.     }
  89.     bool operator<(evt other) const{ return !(evt(p,id,type,inicio)>other);}
  90. };
  91.  
  92. int s, k, w, h;
  93.  
  94. #define MAX_K 10010
  95. #define MAX_W 10010
  96.  
  97. priority_queue<evt, vector<evt>, greater<evt> > pq;
  98. vector<point> hiding(MAX_K);
  99. vector<pair<point, point> > walls(MAX_W);
  100.  
  101. inline bool cmpActive(int a, int b){
  102.   if(a == b) return false;
  103.   if(ccw(seeker, walls[a].first, walls[b].first) && !ccw(seeker, walls[a].second, walls[b].first)){
  104.     return ccw(walls[a].first, walls[a].second, walls[b].first) !=  ccw(walls[a].first, walls[a].second, seeker);
  105.   }
  106.   else{
  107.     return ccw(walls[a].first, walls[a].second, walls[b].second) !=  ccw(walls[a].first, walls[a].second, seeker);
  108.   }
  109. }
  110.  
  111. set<int, bool(*)(int a, int b)> activeLines(cmpActive);
  112. int main(){
  113.     ios_base::sync_with_stdio(false);
  114.     cin.tie(0);
  115.  
  116.     while(cin >> s >> k >> w){
  117.         for (int i = 0; i < k; i++)
  118.             cin >> hiding[i].x >> hiding[i].y;
  119.          
  120.         for(int i = 0; i < w; i++)
  121.             cin >> walls[i].first.x >> walls[i].first.y >> walls[i].second.x >> walls[i].second.y;
  122.            
  123.         // for each seeker kid
  124.         for(int i = 0; i < s; i++){
  125.             seeker = hiding[i]; // set up global variable
  126.             ll ans = 0;
  127.             activeLines.clear(); // clear active (opened) intervals of line segments
  128.             for(int j = 0; j < w; j++){
  129.                 // sort begin-end of an interval by rotation direction( CW or CCW) around seeker
  130.                 if(!ccw(seeker, walls[j].first, walls[j].second)){
  131.                     swap(walls[j].first, walls[j].second);
  132.                 }
  133.                
  134.                 // puts segment's ends in a priority queue, sorted by angle wrt the X axis that
  135.                 // passes through seeker
  136.                 pq.push(evt(walls[j].first,  j, LINE_TYPE, LINE_BEGIN));
  137.                 pq.push(evt(walls[j].second, j, LINE_TYPE, LINE_END));
  138.                
  139.                 // if the segment crosses the X axis, put another segment begining in angle=0 (so the angle sort works)
  140.                 if(quadrant(seeker, walls[j].first) >  quadrant(seeker, walls[j].second)){
  141.                     pq.push(evt(seeker + ax, j, LINE_TYPE, LINE_BEGIN));
  142.                 }
  143.             }
  144.            
  145.             // for each kid that's hiding, put them on priority queue as well
  146.             for(int j = 0; j < k; j++){
  147.                 if(j == i) continue;
  148.                 pq.push(evt(hiding[j], j, KID_TYPE,false));
  149.             }
  150.            
  151.             // sweep circle
  152.             while(!pq.empty()){
  153.                 evt curr = pq.top(); pq.pop(); // current event
  154.                  
  155.                 if(curr.type == LINE_TYPE)
  156.                     if(curr.inicio == LINE_END)
  157.                         // erase active segment from set of active segments
  158.                         activeLines.erase(curr.id);
  159.                     else
  160.                         // add line to active segments
  161.                         activeLines.insert(curr.id);
  162.                 else if(curr.type == KID_TYPE){
  163.                     // if event is of type KID, queries set of active segments for the closer segment to the seeker
  164.                     // if there is any segment between kid and seeker, than the closest segment will be between them as well.
  165.                     // this is also true if there isn't a segment, so it's enough to check just the first segment
  166.                     if(activeLines.empty() || ccw(walls[*activeLines.begin()].first, walls[*activeLines.begin()].second, curr.p) == ccw(walls[*activeLines.begin()].first, walls[*activeLines.begin()].second, seeker)){
  167.                         ans++;
  168.                     }
  169.                 }
  170.             }
  171.             cout << ans << '\n';
  172.         }
  173.     }
  174. }
Advertisement
Add Comment
Please, Sign In to add comment