[TIOJ] 1371. 賢狼之網

題目連結:http://tioj.infor.org/problems/1371
裸的凸包,由左至右掃過去維護上凸包跟下凸包,維護方法就是看加入當前這個點是不是在前面兩個所連線的上方(上凸包的話),如果是就把前一個砍掉,不然就塞進去,下凸包也同理。
不過本題要注意相同高度的點就不用輸出了
#include <bits/stdc++.h>
using namespace std;
typedef long long lld;
struct point{
	lld x,y;
	int id;
	point(){}
	point(lld a,lld b,lld c){x=a;y=b;id=c;}
	point(lld a,lld b){x=a;y=b;}
};
inline lld cross(const point& a,const point& b){
	return a.x*b.y-a.y*b.x;
}
vector<point> dots;
vector<point> cHull;
vector<point> ans;

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	int n;cin>>n;
	for(int i=1;i<=n;i++){
		lld a,b;cin>>a>>b;
		dots.push_back(point(a,b,i));
	}
	sort(dots.begin(),dots.end(),[](const point& a,const point& b){return (a.x!=b.x)?(a.x<b.x):(a.y<b.y);});
	for(int i=0;i<dots.size();i++){
		while(cHull.size()>=2){
			int sz=cHull.size()-1;
			if(cross(point(cHull[sz-1].x-cHull[sz].x, cHull[sz-1].y-cHull[sz].y), \
				point(dots[i].x-cHull[sz].x, dots[i].y-cHull[sz].y))>0ll) break;
			cHull.pop_back();
		}
		cHull.push_back(dots[i]);
	}
	ans=cHull;
	cHull.clear();
	for(int i=0;i<dots.size();i++){
		while(cHull.size()>=2){
			int sz=cHull.size()-1;
			if(cross(point(cHull[sz-1].x-cHull[sz].x, cHull[sz-1].y-cHull[sz].y), \
				point(dots[i].x-cHull[sz].x, dots[i].y-cHull[sz].y))<0ll) break;
			cHull.pop_back();
		}
		cHull.push_back(dots[i]);
	}
	ans.insert(ans.end(), cHull.begin(), cHull.end());
	sort(ans.begin(),ans.end(),[](const point& a, const point& b){return a.id<b.id;});
	ans.resize(distance(ans.begin(), unique(ans.begin(), ans.end(), [](const point& a, const point& b){return a.id==b.id;})));
	cout<<ans.size()<<'\n';
	for(auto i:ans)cout<<i.id<<'\n';
	return 0;
}

留言

這個網誌中的熱門文章

[NPSC] 2009初賽 E. 檸檬汽水傳說

[TIOJ] 1902. 「殿仁.王,不認識,誰啊?」,然後他就死了……

[AtCoder] [經典競程 90 題] 024 - Select +/- One(★2)