首页 > 其他分享 >[题解]UVA10902 Pick-up Sticks

[题解]UVA10902 Pick-up Sticks

时间:2024-07-16 09:19:19浏览次数:4  
标签:UVA10902 Sticks point 题解 线段 ts 相交 vec 木棍

题意简述

多测。给定坐标系上依次给定\(n\)根木棍的起始和终止坐标,按顺序放置这些木棍,询问最终处在最上层的木棍有哪些。

\(n\le 100000\)。保证任意时刻最上层的木棍不超过\(1000\)个。

思路分析

看起来数据范围很刁钻,不过除了暴力以外的方法想不出了,就写了一份上交,结果过了。

思路就是用链表记录最上层的木棍,每放一根木棍就遍历链表,如果有相交的就把这个木棍从链表中移出去。

遍历完链表,再把当前木棍加进去。

难点主要在于如何判断木棍相交。

在平面上判断两线段相交,需要同时使用“快速排斥实验”与“跨立实验”。

所谓快速排斥实验,就是先粗略地判断一下两线段支起的矩形是否相交。如果两个矩形都不相交,两线段肯定也不相交。

但仅仅矩形相交显然不能说线段相交。还需要进行跨立实验。

从线段\(1\)的一端向线段\(2\)的两端作\(2\)个向量。记录红色向量和橙色向量的位置关系为\(A\)(顺时针/逆时针/共线)。
再从线段\(1\)的另一端向\(2\)的两端作\(2\)个向量。记位置关系为\(B\)。
再用线段\(2\)向线段\(1\)重复上面的过程,记位置关系为\(C,D\)。
如果\(A\)和\(B\)都是顺时针或者都是逆时针,或者\(C,D\)都是顺时针或者都是逆时针,则说明两线段不相交。
否则两线段相交。

注意到两向量可能出现共线的情况,这说明一定是某一点在一条线段上了。这种情况仍然是相交,所以不用参与判断。

Code

点击查看代码
#include<bits/stdc++.h>
using namespace std;
struct point{double x,y;};
struct segment{point a,b;};
double cross(point a,point b){return a.x*b.y-b.x*a.y;}
point vec(point a,point b){return {b.x-a.x,b.y-a.y};}
bool intersect(segment a,segment b){
	if(max(b.a.x,b.b.x)<min(a.a.x,a.b.x)||min(b.a.x,b.b.x)>max(a.a.x,a.b.x)||
		max(b.a.y,b.b.y)<min(a.a.y,a.b.y)||min(b.a.y,b.b.y)>max(a.a.y,a.b.y)) return 0;
	double t1=cross(vec(b.a,a.a),vec(b.a,a.b))*cross(vec(b.b,a.a),vec(b.b,a.b));
	double t2=cross(vec(a.a,b.a),vec(a.a,b.b))*cross(vec(a.b,b.a),vec(a.b,b.b));
	if(t1>0||t2>0) return 0;
	return 1;
}
int n;
list<pair<int,segment>> li;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	while(cin>>n){
		if(!n) break;
		li.clear();
		for(int i=1;i<=n;i++){
			segment ts;
			cin>>ts.a.x>>ts.a.y>>ts.b.x>>ts.b.y;
			for(auto it=li.begin();it!=li.end();){
				if(intersect(ts,(*it).second)) it=li.erase(it);
				else it++;
			}
			li.push_back({i,ts});
		}
		cout<<"Top sticks: ";
		bool f=0;
		for(auto i:li){
			if(!f) f=1;
			else cout<<", ";
			cout<<i.first;
			if(!f) f=1,cout<<", ";
		}
		cout<<".\n";
	}
	return 0;
}

标签:UVA10902,Sticks,point,题解,线段,ts,相交,vec,木棍
From: https://www.cnblogs.com/Sinktank/p/18304491

相关文章

  • 题解:P10724 [GESP202406 七级] 区间乘积
    思路看到\(a_i\)很小,不难想到状压一类的东西。考虑把每个数的质因数当做二进制位,这个二进制位的\(1/0\)代表含有这个质因数的奇偶,再做一个异或前缀和,显然完全平方数的质因子个数一定为偶数,根据异或的性质,两个相同的数异或才为\(0\)所以只需要找到异或前缀和中相同的数的个......
  • 迷宫守卫 题解
    给个题目链接:迷宫守卫。下面直接开始讲了。发现一个事情,省选的题已经不怎么考板子难度很高的题了,现在考的都是思维难度非常高的题。首先,我们考虑字典序的性质,如果第一位劣,那么后面无论多优都没用,所以我们要优先满足靠前的位置。于是我们考虑使用二分来找出第一个数,后面以此类......
  • 题解:SP11469 SUBSET - Balanced Cow Subsets
    SP11469(折半搜索)题目大意:给出$N$个数,求可以被分成两个和相等的集合的子集数。思路分析:首先考虑朴素的DFS,每个数有三种情况:选为$A$集合,选为$B$集合,两个集合都不选。暴力DFS时间复杂度为$3^{20}$。观察到$N$很小,而$3^{10}$是可以通过本题的,于是考虑折半搜索。我......
  • P10720 [GESP202406 五级] 小杨的幸运数字 题解
    题意如果一个数的质因子中只有两个不同的数则输出\(1\),否则输出\(0\)。思路从第一个质因子遍历到\(sum\)的话很明显是\(O(nt)\)最大是\(n^{10}\)很明显会炸掉。所以遍历到\(sum\)是不行的,考虑正整数\(n\)最大的质因数是\(\sqrt{n}\)所以遍历到\(\sqrt{n}\)即......
  • 题解:SP10502 VIDEO - Video game combos
    大意构造一个长度为\(k\)(\(k\)是给定的)的串\(x\),使得对于\(∀1\leqi\leqn,s_i\)在\(x\)中的出现次数之和最大。输出这个最大值。思考考虑对\(s_i\)建AC自动机,然后dp。记\(dp[i][u]\)表示为长度为\(i\)的字符串,且当前已计算的节点是Trie上的编号为\(u......
  • 【题解】 [CSP-J 2021 T1] 分糖果
    题目描述题目大意给定正整数\(n\)、\(L\)、\(R\),求\(\max_{i\in\left[L,R\right]}{i\bmodn}\)。思路题目主要考察:分类讨论。众所周知,对于\(\forallx\),有$(x\bmodn)\in\left[0,n-1\right]$。可以分为两种情况讨论:如果\(\left\lfloor\frac{L......
  • 题解:CF1833F Ira and Flamenco
    思路因为要一个长度为\(m\)的,且最大与最小的元素之差小于等于\(m\)所以序列应为\(a_i,a_i+1,a_i+2\dots,a_i+m-1\),所以满足要求的序列之需要连续\(m\)个就行了,这个最开始排序,去重后用lower_bound求一下小于\(a_i+m-1\)的数有没有\(m\)个就行了。考虑满足要求序列的......
  • P8704 [蓝桥杯 2020 省 A1] 填空问题 题解
    题目传送门A.跑步训练我们经过仔细观察,可以发现每222分钟就会消耗300300......
  • P2754 [CTSC1999] 家园 / 星际转移问题题解
    开始时,将源点连一条权值为\(k\)的边到地球。然后以时间分层,从上一层的点连接到下一层的点,权值为飞船载人数量,并将代表月球的点连接到汇点。每加一层,在上一层的基础上进行增广,看能不能增加流量,如果流量变为\(k\),那么证明运送完成。可以证明枚举时间最多到\(1500\),图的点数不......
  • SP4063 MPIGS - Sell Pigs / P4638 [SHOI2011] 银行家题解
    考虑使用网络流。建立源点\(S\)和汇点\(T\)。每个人作为一个点,将它们与汇点\(T\)连接,权值为需要的猪的数量。然后对于每个人,如果和之前的某个人开了相同的猪圈,那么就将之前的那个人的点与这个人的点连接。如果猪圈还没有被开过,就从源点\(S\)连接这个点,权值为猪圈猪的初......