hdu 1558

A segment and all segments which are connected with it compose a segment set. The size of a segment set is the number of segments in it. The problem is to find the size of some segment set.  

 

Input

In the first line there is an integer t - the number of test case. For each test case in first line there is an integer n (n<=1000) - the number of commands.  

There are two different commands described in different format shown below:  

P x1 y1 x2 y2 - paint a segment whose coordinates of the two endpoints are (x1,y1),(x2,y2).  
Q k - query the size of the segment set which contains the k-th segment.  

k is between 1 and the number of segments in the moment. There is no segment in the plane at first, so the first command is always a P-command.  
 

Output

For each Q-command, output the answer. There is a blank line between test cases.
 

Sample Input

    
    
1 10 P 1.00 1.00 4.00 2.00 P 1.00 -2.00 8.00 4.00 Q 1 P 2.00 3.00 3.00 1.00 Q 1 Q 3 P 1.00 4.00 8.00 2.00 Q 2 P 3.00 3.00 6.00 -2.00 Q 5
 

Sample Output

    
    
1 2 2 2 5
 
这题重点是几何,还有就是注意输出的格式问题
代码
#include <iostream>

using namespace std;
int pre[1100];
int num[1100];
struct point
{
  double x,y;
};
struct xian
{
  point a,b;
}hehe[1100];
int find(int x)
{
  int r=x;
  while(pre[r]!=r)
  {
   r=pre[r];
  }
  int i=x,j;
  while(i!=r)
  {
   j=pre[i];
   pre[i]=r;
   i=j;
  }
  return r;
}
void join(int x,int y)
{
 int fx=find(x),fy=find(y);
 if(fx!=fy)
 {
  pre[fx]=fy;
  num[fy]=num[fy]+num[fx];
 }
}
double xm(point a,point b,point c)
{
 return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
bool seg(point a,point b,point c)
{
 return c.x>=min(a.x,b.x)&&c.x<=max(a.x,b.x)&&c.y>=min(a.y,b.y)&&c.y<=max(a.y,b.y);
}
bool cross(point a,point b,point c,point d)
{
  double d1,d2,d3,d4;
  d1=xm(c,d,a);
  d2=xm(c,d,b);
  d3=xm(a,b,c);
  d4=xm(a,b,d);
  if(d1*d2<0&&d3*d4<0) return 1;
  else if(d1==0&&seg(c,d,a)) return 1;
  else if(d2==0&&seg(c,d,b)) return  1;
  else if(d3==0&&seg(a,b,c)) return 1;
  else if(d4==0&&seg(a,b,d)) return 1;
  return 0;
}
int main()
{
    int t,n,k,tmp;
    char c;
    cin>>t;
    while(t--)
    {
     k=0;
     cin>>n;
     for(int i=1;i<=n;i++)
     {
      pre[i]=i;
      num[i]=1;
     }
     for(int i=1;i<=n;i++)
     {
      cin>>c;
      if(c=='P')
      {
       k++;
       cin>>hehe[k].a.x>>hehe[k].a.y>>hehe[k].b.x>>hehe[k].b.y;
       for(int j=1;j<k;j++)
       {
        if(cross(hehe[k].a,hehe[k].b,hehe[j].a,hehe[j].b))
          join(j,k);
       }
      }
      else
      {
       cin>>tmp;
       cout<<num[find(tmp)]<<endl;
      }
     }
     if(t)
     cout<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值