题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=128
题意:给出平面上一些点,将其连成一个封闭图形。要求每个顶点处都是直角。
思路:首先分别按照x和y排序一次。比如按照x排序后,点必然两两配对即他们的x是一样的。然后就是判断不相交,也就是多边形是无自环的。这个用树状数组。对于每一对顶点记录上下关系和左右关系。对于一对点的下面那个点,当将其插入树状数组的时候若发现树状数组中有位于该点和其配对点之间的点,则有环。因为这个点所连的线必然与连接该点与其配对点的线相交。
const int MAX=10005;
class BIT
{
public:
int a[MAX<<1];
void insert(int pos,int x)
{
while(pos<MAX*2)
{
a[pos]+=x;
pos+=pos&(-pos);
}
}
int query(int pos)
{
int ans=0;
while(pos)
{
ans+=a[pos];
pos-=pos&(-pos);
}
return ans;
}
};
struct point
{
int x,y;
};
BIT bit;
point p[MAX];
int n,s[MAX],pos[MAX],up[MAX],L[MAX];
int find(int x)
{
if(s[x]!=x) s[x]=find(s[x]);
return s[x];
}
void Union(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y) s[x]=y;
}
int cmpx(int a,int b)
{
if(p[a].x!=p[b].x) return p[a].x<p[b].x;
return p[a].y<p[b].y;
}
int cmpy(int a,int b)
{
if(p[a].y!=p[b].y) return p[a].y<p[b].y;
return p[a].x<p[b].x;
}
int deal()
{
int ans=0,i,j,k,t;
FOR0(i,n) s[i]=i;
sort(pos,pos+n,cmpx);
for(i=0;i<n;i+=2)
{
j=pos[i];
k=pos[i+1];
if(p[j].x!=p[k].x) return 0;
ans+=p[k].y-p[j].y;
up[j]=k;
Union(j,k);
}
sort(pos,pos+n,cmpy);
for(i=0;i<n;i+=2)
{
j=pos[i];
k=pos[i+1];
if(p[j].y!=p[k].y) return 0;
ans+=p[k].x-p[j].x;
L[j]=1;
Union(j,k);
}
k=find(0);
FOR1(i,n-1) if(find(i)!=k) return 0;
sort(pos,pos+n,cmpx);
FOR0(i,n)
{
j=pos[i];
k=p[up[j]].y;
t=p[j].y;
if(up[j]&&bit.query(k+MAX)-bit.query(t+MAX+1)) return 0;
if(L[j]) bit.insert(t+MAX+1,1);
else bit.insert(t+MAX+1,-1);
}
return ans;
}
int main()
{
scanf("%d",&n);
int i;
FOR0(i,n) scanf("%d%d",&p[i].x,&p[i].y),pos[i]=i;
printf("%d\n",deal());
return 0;
}