Segment set

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3699    Accepted Submission(s): 1394
Problem Description
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
 
Author
LL
 
Source
 

题意:二维坐标上给你n条小段,每次询问的时候求询问线段全部存在连接关系的线段的数量

这题非常水。可是对于高中数学没学好或者像我这样的遗忘到差点儿相同的群体来说。太纠结了。

关键点在于证明两线段是否有连接关系,比方交叉。顶点同样,都算连接

因为遗忘的差点儿相同了。就网上暂时复习了向量积。花了不少时间才消化KO。。

事实上网上的都是标准说法,对于我们这样的不喜欢看书的孩纸来说是天书。所以我把这抽象化的东东用日常一些的语言解释一遍。

假如两线段的两顶点各自是ab和cd,要么证明他们平行且有重叠,重叠就是说当中一线段有顶点在还有一线段中。或者证明他们没有平行之后向量ab在向量ac和向量ad之间,同一时候向量ca在向量ca和向量cb之间。看图。。

从途中能够看到,红色箭头是不符合cd在ca与cb中间的,这就是为什么要两个线段的端点都要取出来验证了,还有就是平行可是不共线,或者平行共线可是由于是线段不相连,所以不能算连接,以下说公式。。。

由于线段A(x1,y1,x2,y2)(x和y表示两个顶点的坐标)斜率L=(y2 - y1)/(x2 - x1)如果要求的是ac与ad的斜率差,那么就是Lac-Lad。然后把公式代入再展开就得到了我代码中dd函数里面的公式,它是用来求斜率差值的。而里面的cmp函数中用dd函数求了4次,这是由于要直接证明ab在ac和ad中间不简单。那么换一方案,直接比較斜率差值,就像上图中左下角的那个图,求出ac和ad的斜率差值还有bc和bd的斜率差值。如果你把线段的斜率用图画出来,你会发现两个差值相乘能推断ab和cd是否交叉。我画个图得了。

。。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamluZ2RpYW5pdG5hbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

这样就攻克了ab与cd存在交叉可是ab太短了没办法从cd中间插过去的问题- -。确定插过去了是cmp函数中d1*d2和d3*d4都小于零的前提,d1*d2是保证ab插过cd,d3*d4是保证cd插过ab,咳咳咳。太邪恶了,baby你懂了没?

总述一下,先考虑平行问题,平行情况下是否有重叠。然后是可能存在交叉的问题,推断好ab从cd中间穿过且ab够长,同一时候cd对ab也要推断一次,这样就能够AC了

注意:数据类型要弄好,由于int会把double的小数位去掉。1.1会变成1,咳咳。太可恶了。就是这个WA我到死。。总之,这个题非常经典。我是这么觉得的

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct
node
{
double
x1,x2,y1,y2;
}
s[1111];
int
f[1111],num[1111];
double
cc=1e-7;
int
Find(int x)
{
return
f[x]=(f[x]==x?x:Find(f[x]));
}
void
Union(int x,int y)
{

x=Find(x);
y=Find(y);
if(
x==y)return;//已经在一个集合中就不要反复了
f[x]=y;
num[y]+=num[x];//联系两个线段集合的时候顺便把集合中线段数量集中起来
}
double
Max(double a,double b)
{
return
a>b?a:b;
}
double
Min(double a,double b)
{
return
a<b?a:b;
}
double
dd(double x1,double y1,double x2,double y2,double x3,double y3)//两线段的斜率差
{
return (
x2-x1)*(y3-y1)-(y2-y1)*(x3-x1);
}
int
ddd(double x1,double y1,double x2,double y2,double x3,double y3)//共线情况下是否有重叠
{
if(
Max(x1,x2)>=x3&&Min(x1,x2)<=x3&&Max(y1,y2)>=y3&&Min(y1,y2)<=y3)
return
1;
return
0;
}
int
cmp(node a,node b)
{
double
d1,d2,d3,d4;
d1=dd(a.x1,a.y1,a.x2,a.y2,b.x1,b.y1);
d2=dd(a.x1,a.y1,a.x2,a.y2,b.x2,b.y2);
d3=dd(b.x1,b.y1,b.x2,b.y2,a.x1,a.y1);
d4=dd(b.x1,b.y1,b.x2,b.y2,a.x2,a.y2);//cout<<d1<<d2<<" "<<d3<<d4<<endl;
if(d1*d2<0&&d3*d4<0)return 1;//cout<<"X"<<endl;//斜率差一正一负能够得出两不共线线段交叉。上面有本人的个人看法说明
if(d1==0&&ddd(a.x1,a.y1,a.x2,a.y2,b.x1,b.y1))return 1;//cout<<"A"<<endl;//共线的时候看看是否有重叠
if(d2==0&&ddd(a.x1,a.y1,a.x2,a.y2,b.x2,b.y2))return 1;//cout<<"S"<<endl;
if(d3==0&&ddd(b.x1,b.y1,b.x2,b.y2,a.x1,a.y1))return 1;//cout<<"D"<<endl;
if(d4==0&&ddd(b.x1,b.y1,b.x2,b.y2,a.x2,a.y2))return 1;//cout<<"F"<<endl;
return 0;
}
int main (void)
{
int
t,n,i,j,k,l;
char
c;
scanf("%d",&t);
while(
t--&&scanf("%d",&n))
{
for(
i=0;i<1111;i++)f[i]=i,num[i]=1;
l=0;
while(
n--)
{

scanf("%*c%c",&c);
if(
c=='P')
{

scanf("%lf%lf%lf%lf",&s[l].x1,&s[l].y1,&s[l].x2,&s[l].y2);
for(
i=0;i<l;i++)//与之前记录的全部线段匹配连接关系
if(
cmp(s[i],s[l]))//假设有连接
/*cout<<"A"<<endl,*/Union(i,l);//并查集把线段联系起来
l++;
}else
{

scanf("%d",&k);
printf("%d\n",num[Find(k-1)]);
}

//for(i=0;i<l;i++)cout<<num[i]<<" ";cout<<endl;
}
if(
t)puts("");//妈啵的,这里没写PE了
}
return
0;
}

HDU--1558--Segment set--并查集***经典***的更多相关文章

  1. hdu 1558 Segment set (并查集)

    Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  2. hdu 1558 (线段相交+并查集) Segment set

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐 ...

  3. hdu 1558 线段相交+并查集路径压缩

    Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. hdu 1558 线段相交+并查集

    题意:要求相交的线段都要塞进同一个集合里 sol:并查集+判断线段相交即可.n很小所以n^2就可以水过 #include <iostream> #include <cmath> ...

  5. HDU 1232 (畅通工程) 并查集经典模板题

    Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通 ...

  6. HDU 1811 拓扑排序 并查集

    有n个成绩,给出m个分数间的相对大小关系,问是否合法,矛盾,不完全,其中即矛盾即不完全输出矛盾的. 相对大小的关系可以看成是一个指向的条件,如此一来很容易想到拓扑模型进行拓扑排序,每次检查当前入度为0 ...

  7. hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)

    hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...

  8. HDU 1558 Segment set( 判断线段相交 + 并查集 )

    链接:传送门 题意:输入一个数 n 代表有 n 组操作,P 是在平面内加入一条线段,Q x 是查询第 x 条线段所在相交集合的线段个数 例如:下图 5 与 1.2 相交,1 与 3 相交,2 与 4 ...

  9. <hdu - 1232> 畅通工程 并查集问题 (注意中的细节)

    本题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232  结题思路:因为题目是汉语的,那我就不解释题意了,要求的是最少建设的道路,我们可以用并查集来做这 ...

随机推荐

  1. [转]浏览器缓存详解: expires, cache-control, last-modified, etag详细说明

    最近在对CDN进行优化,对浏览器缓存深入研究了一下,记录一下,方便后来者 画了一个草图: 每个状态的详细说明如下: 1.Last-Modified 在浏览器第一次请求某一个URL时,服务器端的返回状态 ...

  2. 安卓通过UDP协议传输数据,中文乱码的问题

    公司最近需要往智能家居方面发展,需要用到UDP协议传输数据,在网上找到了一些资料,但是发现传输中文的时候有乱码的现象,经过我多番捣鼓,终于解决了这个问题,下面贴上关键代码 客户端: public cl ...

  3. github添加公钥出现 github ssh key Key is invalid. Ensure you've copied the file correctly的解决办法

    因为在公钥查看的时候可能是利用了vim明明查看,所以会有换行,导致这个错误,解决方法是用cat命令查看文件,或者其他方式查看,总之公钥不能有换行.

  4. 如何写出高性能SQL语句(文章摘自web开发者)

    (声明:本文内容摘自web开发者,仅供收藏学习之用,如有侵权请作者联系博主,博主将在第一时间删除) 原文地址:http://www.admin10000.com/document/484.html 1 ...

  5. JavaOO知识点小结一

    Java语言的特点是什么?简单 面向对象 跨平台 多线程 健壮性安全性 垃圾回收机制如何编译和执行java文件?产生帮助文档用什么命令?编译: javac 文件名执行: java 类名产生帮助文档 j ...

  6. DNN结构演进History—CNN-GoogLeNet :Going Deeper with Convolutions

    抄袭了一片文章,进行少量修改:http://www.gageet.com/2014/09203.php       作者:Christian Szegedy( google )  刘伟(北卡罗来纳  ...

  7. 通过Static 字段来维护状态是不是一个好主意

    static是申明静态字段.静态方法或者静态类的修饰符.使用static申明的字段属于类型本身而不属于任何字段,声明的类也具有一些特别特性,比如不能实例化,不能继承等.用通俗化的语言来说,static ...

  8. beetl模板入门例子

    加入maven依赖 <dependency> <groupId>org.beetl</groupId> <artifactId>beetl-core&l ...

  9. 微信jssdk图片上传

    一.html页面如下: <div class="weui-cell"> <div class="weui-cell__hd"></ ...

  10. Java 将要上传的文件上传至指定路径代码实现

    代码: /** * 上传文件到指定路径 * @param mFile 要上传的文件 * @param path 指定路径 */ public static void uploadFile(Multip ...