[POI2008]Mirror Trap

題目大意:
  一個$n(n\le10^5)$個頂點的格點多邊形,每條邊平行於網格線,每一個角度數均爲$90^\circ$或$270^\circ$,周長小於$3\times10^5$,每一個頂點能夠安裝激光發射器或接收器,發射(接收)器能夠發射(接收)一條向多邊形內部的、與網格線成$45^\circ$夾角的射線,射線會在多邊形邊上發生鏡面反射,直到被某個接收器接收。求任意一種發射器與接收器的配對方案。git

思路:
  BZOJ上只要求求出發射器的個數,答案顯然就是$\frac n2$。原題須要輸出方案,考慮任意一條與網格線成$45^\circ$的斜線上,對於全部點$(x,y)$,$x+y$或$x-y$必定是相等的,因爲多邊形周長有限,能夠預處理出周長上的全部整點,對於$x+y$和$x-y$相等的點排序,暴力模擬鏡面反射的過程便可。spa

 1 #include<map>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<vector>
 5 #include<algorithm>
 6 inline int getint() {  7     register char ch;  8     register bool neg=false;  9     while(!isdigit(ch=getchar())) if(ch=='-') neg=true;  10     register int x=ch^'0';  11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');  12     return neg?-x:x;  13 }  14 const int N=1e5;  15 using Point=std::pair<int,int>;  16 int n;  17 Point p[N];  18 bool vis[N];  19 std::map<Point,int> v,dir;  20 std::map<int,std::vector<Point>> map1,map2;  21 std::pair<int,int> dxy(const int &i) {  22     if(p[i].first==p[(i+1)%n].first&&p[i].second==p[(i-1+n)%n].second&&p[i].first<p[(i-1+n)%n].first&&p[i].second<p[(i+1)%n].second) return std::make_pair(1,1);  23     if(p[i].first==p[(i-1+n)%n].first&&p[i].second==p[(i+1)%n].second&&p[i].first<p[(i+1)%n].first&&p[i].second>p[(i-1+n)%n].second) return std::make_pair(1,-1);  24     if(p[i].first==p[(i+1)%n].first&&p[i].second==p[(i-1+n)%n].second&&p[i].first>p[(i-1+n)%n].first&&p[i].second>p[(i+1)%n].second) return std::make_pair(-1,-1);  25     if(p[i].first==p[(i-1+n)%n].first&&p[i].second==p[(i+1)%n].second&&p[i].first>p[(i+1)%n].first&&p[i].second<p[(i-1+n)%n].second) return std::make_pair(-1,1);  26     if(p[i].first==p[(i-1+n)%n].first&&p[i].second==p[(i+1)%n].second&&p[i].first>p[(i+1)%n].first&&p[i].second>p[(i-1+n)%n].second) return std::make_pair(1,1);  27     if(p[i].first==p[(i+1)%n].first&&p[i].second==p[(i-1+n)%n].second&&p[i].first>p[(i-1+n)%n].first&&p[i].second<p[(i+1)%n].second) return std::make_pair(1,-1);  28     if(p[i].first==p[(i-1+n)%n].first&&p[i].second==p[(i+1)%n].second&&p[i].first<p[(i+1)%n].first&&p[i].second<p[(i-1+n)%n].second) return std::make_pair(-1,-1);  29     if(p[i].first==p[(i+1)%n].first&&p[i].second==p[(i-1+n)%n].second&&p[i].first<p[(i-1+n)%n].first&&p[i].second>p[(i+1)%n].second) return std::make_pair(-1,1);  30     return std::make_pair(0,0);  31 }  32 int main() {  33     n=getint();  34     for(register int i=0;i<n;i++) {  35         const int x=getint(),y=getint();  36         v[p[i]=(Point){x,y}]=i;  37  }  38     for(register int i=0;i<n;i++) {  39         const int j=(i+1)%n;  40         if(p[i].first==p[j].first) {  41             const int &x=p[i].first;  42             for(register int y=p[i].second;y!=p[j].second;y+=p[j].second>y?1:-1) {  43                 map1[x+y].push_back((Point){x,y});  44                 map2[x-y].push_back((Point){x,y});  45                 if(y!=p[i].second) dir[(Point){x,y}]=1;  46  }  47  }  48         if(p[i].second==p[j].second) {  49             const int &y=p[i].second;  50             for(register int x=p[i].first;x!=p[j].first;x+=p[j].first>x?1:-1) {  51                 map1[x+y].push_back((Point){x,y});  52                 map2[x-y].push_back((Point){x,y});  53                 if(x!=p[i].first) dir[(Point){x,y}]=-1;  54  }  55  }  56  }  57     for(auto &p:map1) std::sort(p.second.begin(),p.second.end());  58     for(auto &p:map2) std::sort(p.second.begin(),p.second.end());  59     printf("%d\n",n/2);  60     for(register int i=0;i<n;i++) {  61         if(vis[i]) continue;  62         vis[i]=true;  63         int x=p[i].first,y=p[i].second,dx,dy;  64         if(dxy(i)==std::make_pair(1,1)) {  65             const auto t=std::upper_bound(map2[x-y].begin(),map2[x-y].end(),(Point){x,y});  66             x=t->first,dx=1;  67             y=t->second,dy=1;  68  }  69         if(dxy(i)==std::make_pair(1,-1)) {  70             const auto t=std::upper_bound(map1[x+y].begin(),map1[x+y].end(),(Point){x,y});  71             x=t->first,dx=1;  72             y=t->second,dy=-1;  73  }  74         if(dxy(i)==std::make_pair(-1,-1)) {  75             const auto t=std::lower_bound(map2[x-y].begin(),map2[x-y].end(),(Point){x,y})-1;  76             x=t->first,dx=-1;  77             y=t->second,dy=-1;  78  }  79         if(dxy(i)==std::make_pair(-1,1)) {  80             const auto t=std::lower_bound(map1[x+y].begin(),map1[x+y].end(),(Point){x,y})-1;  81             x=t->first,dx=-1;  82             y=t->second,dy=1;  83  }  84         for(;!v.count((Point){x,y})||std::make_pair(-dx,-dy)!=dxy(v[(Point){x,y}]);) {  85             if(dir[(Point){x,y}]==1) dx=-dx;  86             if(dir[(Point){x,y}]==-1) dy=-dy;  87             if(dx==1&&dy==1) {  88                 const auto t=std::upper_bound(map2[x-y].begin(),map2[x-y].end(),(Point){x,y});  89                 x=t->first;  90                 y=t->second;  91  }  92             if(dx==1&&dy==-1) {  93                 const auto t=std::upper_bound(map1[x+y].begin(),map1[x+y].end(),(Point){x,y});  94                 x=t->first;  95                 y=t->second;  96  }  97             if(dx==-1&&dy==-1) {  98                 const auto t=std::lower_bound(map2[x-y].begin(),map2[x-y].end(),(Point){x,y})-1;  99                 x=t->first; 100                 y=t->second; 101  } 102             if(dx==-1&&dy==1) { 103                 const auto t=std::lower_bound(map1[x+y].begin(),map1[x+y].end(),(Point){x,y})-1; 104                 x=t->first; 105                 y=t->second; 106  } 107  } 108         vis[v[(Point){x,y}]]=true; 109         printf("%d %d\n",i+1,v[(Point){x,y}]+1); 110  } 111     return 0; 112 }
相關文章
相關標籤/搜索