Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdlib>
- #include <cstdio>
- #include <algorithm>
- #include <vector>
- #include <set>
- using namespace std;
- class punkt
- {public:
- int indeks;
- int x,y;
- int sasiad_pionowy, sasiad_poziomy;
- signed char kierunek_x, kierunek_y;
- bool odwiedzony;
- bool wewnetrzny; // czy wiercholek skierowany jest do wewnatrz.
- punkt(){};
- punkt(int _x, int _y, int i){ indeks=i; x=_x; y=_y; sasiad_pionowy=-1; sasiad_poziomy=-1; odwiedzony=false; }
- };
- typedef punkt* ppunkt ;
- struct sortuj_x_y
- {
- bool operator () (const punkt* a, const punkt* b)const
- { return ((a->x < b->x) || ( (a->x == b->x)&&(a->y < b->y) ) ) ; }
- }sortxy;
- struct sortuj_x
- {
- bool operator () (const punkt* a, const punkt* b)const
- { return (a->x < b->x) ; }
- };
- struct sortuj_y
- {
- bool operator () (const punkt* a, const punkt* b)const
- { return (a->y < b->y) ; }
- };
- struct sortuj_y_x
- {
- bool operator () ( punkt *a, punkt *b)const
- { return ((a->y < b->y) || ( (a->y == b->y)&&(a->x < b->x) ) ) ; }
- }sortyx;
- inline signed char norm_kier(int k)//normalizuj liczbę do jej znaku
- {
- if (k==0)return 0;
- else
- return (k>=0)?1:-1;
- }
- int iloczyn ( vector <punkt > & punkty, int i )
- {
- int n=punkty.size();
- int X2 = norm_kier( punkty[(i+1)%n].x - punkty[i].x );
- int Y2 = norm_kier( punkty[(i+1)%n].y - punkty[i].y );
- int X1 = norm_kier( punkty[i].x - punkty[(n+i-1)%n].x );
- int Y1 = norm_kier( punkty[i].y - punkty[(n+i-1)%n].y );
- return (X2*Y1)-(X1*Y2);
- }
- int main()
- {
- int n;
- scanf("%d",&n);
- vector <punkt > punkty(n);
- for (int i=0;i<n;i++)
- {
- int x,y;
- scanf("%d %d",&x,&y);
- punkty[i]=punkt(x,y,i);
- }
- for (int i=0;i<n;i++)
- {
- punkty[i].kierunek_x= norm_kier(punkty[(i+1)%n].x+punkty[(n+i-1)%n].x - 2*punkty[i].x);
- punkty[i].kierunek_y= norm_kier(punkty[(i+1)%n].y+punkty[(n+i-1)%n].y - 2*punkty[i].y);
- }
- vector<punkt*> pun(n);
- for (int i=0;i<n;i++)
- {
- pun[i]=(&punkty[i]);
- }
- std::sort(pun.begin(),pun.end(),sortyx);//najpierw po x, potem po y
- int it = pun[0]->indeks; //ekstremalny wierzcholek nie moze byc wewnatrznym
- int zewnetrzny = iloczyn( punkty,it );
- for (int i=0;i<n;i++)
- {
- punkty[i].wewnetrzny=( iloczyn(punkty,i)!=zewnetrzny );
- }
- {
- set <punkt*,sortuj_x> wolne;
- set <punkt*,sortuj_x>::iterator A,B;
- int k=0;
- do
- {
- int miotla_y=pun[k]->y;
- while ((k<n)&&(pun[k]->y==miotla_y))
- {
- punkt *a,*b;
- a = pun[k];
- b = pun[k+1];
- k+=2;
- A = wolne.lower_bound(a);
- B = wolne.upper_bound(b);
- //if (A==wolne.end())printf("end");
- if ( (A!=wolne.end()) && (A!=B))//coś znalezlismy
- {
- if( (a->x == (*A)->x) &&abs(a->indeks - (*A)->indeks)!=1 )
- {
- a->sasiad_pionowy = (*A)->indeks;
- (*A)->sasiad_pionowy = a->indeks;
- }
- // if (A==wolne.end())printf("NIE");
- B--; //tam mozę być kandydat; Poprzednik zawsze istnieje bo A=\=B
- if(( b->x == (*B)->x ) &&abs(b->indeks - (*B)->indeks)!=1 )
- {
- b->sasiad_pionowy = (*B)->indeks;
- (*B)->sasiad_pionowy = b->indeks;
- }
- B++;
- }
- wolne.erase(A,B);
- if ((a->kierunek_y<0)&&(a->wewnetrzny))
- {
- wolne.insert(a);
- }
- if ((b->kierunek_y<0)&&(b->wewnetrzny))
- {
- wolne.insert(b);
- }
- }//while (pun[k]->y==miotla_y)
- }while (k<n);
- }
- //////////////////////copypasta
- std::sort(pun.begin(),pun.end(),sortxy);//najpierw po y, potem po x
- {
- set <punkt*,sortuj_y> wolne;
- set <punkt*,sortuj_y>::iterator A,B;
- int k=0;
- do
- {
- int miotla_x=pun[k]->x;
- while ((k<n)&&(pun[k]->x==miotla_x))
- {
- punkt *a,*b;
- a = pun[k];
- b = pun[k+1];
- k+=2;
- A = wolne.lower_bound(a);
- B = wolne.upper_bound(b);
- //if (A==wolne.end())printf("end");
- if ( (A!=wolne.end()) && (A!=B))//coś znalezlismy
- {
- if( (a->y == (*A)->y) &&abs(a->indeks - (*A)->indeks)!=1 )
- {
- a->sasiad_poziomy = (*A)->indeks;
- (*A)->sasiad_poziomy = a->indeks;
- }
- //if (A==wolne.end())printf("NIE");
- B--; //tam mozę być kandydat; Poprzednik zawsze istnieje bo A=\=B
- if(( b->y == (*B)->y ) &&abs(b->indeks - (*B)->indeks)!=1 )
- {
- b->sasiad_poziomy = (*B)->indeks;
- (*B)->sasiad_poziomy = b->indeks;
- }
- B++;
- }
- wolne.erase(A,B);
- if ((a->kierunek_x<0)&&(a->wewnetrzny))
- {
- wolne.insert(a);
- }
- if ((b->kierunek_x<0)&&(b->wewnetrzny))
- {
- wolne.insert(b);
- }
- }//while (pun[k]->y==miotla_y)
- }while (k<n);
- }
- ////////////////////////copypasta
- int wynik = (n-4)/2;
- //printf("/n/n");
- for (int i=0; i<n;i++)
- {
- int licznik=0;
- if (!punkty[i].odwiedzony)
- {
- int j=i;
- //printf("%d %d\n",punkty[j].x,punkty[j].y);
- while (1)
- {
- if (punkty[j].sasiad_pionowy==-1) break;
- j = punkty[j].sasiad_pionowy;
- if (punkty[j].odwiedzony) break;
- licznik++;
- punkty[j].odwiedzony=true;
- if (punkty[j].sasiad_poziomy==-1) break;
- j = punkty[j].sasiad_poziomy;
- if (punkty[j].odwiedzony) break;
- licznik++;
- punkty[j].odwiedzony=true;
- }
- j=i;
- punkty[j].odwiedzony=true;
- while (1)
- {
- if (punkty[j].sasiad_poziomy==-1) break;
- j = punkty[j].sasiad_poziomy;
- if (punkty[j].odwiedzony) break;
- licznik++;
- punkty[j].odwiedzony=true;
- if (punkty[j].sasiad_pionowy==-1) break;
- j = punkty[j].sasiad_pionowy;
- if (punkty[j].odwiedzony) break;
- licznik++;
- punkty[j].odwiedzony=true;
- }
- //printf("%d %d\n",i,licznik);
- wynik -= (licznik+1)/2;
- }//if (punkty[i].odwiedzony)
- }
- printf("%d\n",wynik);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement