牛客第二场-处女座的签到题-毒瘤题-STL的nth_element()

平面上有n个点,问:平面上所有三角形面积第k大的三角形的面积是多少?

输入描述:

第一行T,表示样例的个数。
对于每一组样例,第一行两个整数n和k,
接下来n行,每行两个整数x,y表示点的坐标
T<=80
3<=n<=100
-10 9<=x,y<=10 9
对于每一组样例,保证任意两点不重合,且能构成的三角形的个数不小于k

输出描述:

对于每一组样例,输出第k大三角形的面积,精确到小数点后两位(四舍五入)。
示例1

输入

复制
1
4 3
1 1
0 0
0 1
0 -1

输出

复制
0.50

说明

样例中一共能构成3个三角形,面积分别为0.5,0.5,和1,面积第3大的为0.5

首先这道题要用到平面向量求三角形面积的公式,有(x1,y1),(x2,y2),(x3,y3)三个点,则他们组成的三角形(无法组成三角形结果就是0)的面积是S = abs( (x2-x1)(y3-y1) - (x3-x1)(y2-y1))/2.最后要四舍五入,其实是在迷惑你,结果是整数,/2的结果,小树部分要么是0.50,要么是0.00,判断一下他是技术还是偶数就可以了。
最后也就是最难得地方就是复杂读的问题,求第k大的数,如果直接对所有的排序然后输出结果,肯定超时。
如果用优先队列,也会超时。
合理居然要用到,STL的nth_element()函数。
STL中的nth_element()方法的使用 通过调用nth_element(start, start+n, end)
方法可以使第n小元素处于第n位置(从0开始,其位置是下标为 n的元素),
并且比这个元素小的元素都排在这个元素之前,比这个元素大的元素都排在这个元素之后,
但不能保证他们是有序的
最后送上AC code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<cstring>
#include<string>
#include<cmath>

using namespace std;

typedef long long LL;

#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define per(i,a,b) for(int i = a;i <= b;++i)
#define rep(i,a,b) for(int i = a;i >= b;--i)
const int maxn = 1e2;
int n = 0,k = 0; 
struct node{
	LL x,y;
};
node a[maxn+10];
vector<LL> vt;
int main(){
	//std::ios::sync_with_stdio(false);
	
	int T = 0;
	scanf("%d",&T);
	while(T--){
		//priority_queue<LL> pq;
		vt.clear();
		scanf("%d %d",&n,&k);
		per(i,1,n){
			scanf("%lld %lld",&a[i].x,&a[i].y);
		} 
		per(i,1,n){
			per(j,i+1,n){
				per(k,j+1,n){
					LL sum = abs((a[j].x-a[i].x)*(a[k].y-a[i].y) - (a[k].x-a[i].x)*(a[j].y-a[i].y));
					vt.push_back(sum);
					//pq.push(sum);
				}
			}
		}
		//sort(vt.begin(),vt.end(),cmp);//复杂度太高 
		nth_element(vt.begin(),vt.begin()+n*(n-1)*(n-2)/6-k,vt.end());
		/*
		STL中的nth_element()方法的使用 通过调用nth_element(start, start+n, end) 
		方法可以使第n小元素处于第n位置(从0开始,其位置是下标为 n的元素),
		并且比这个元素小的元素都排在这个元素之前,比这个元素大的元素都排在这个元素之后,
		但不能保证他们是有序的
		*/ 
		LL ans = vt[n*(n-1)*(n-2)/6-k];
		/* 
		LL ans = 0;
		while(k--){//优先队列的复杂度偏高 
			ans = pq.top();
			pq.pop();
		}
		*/
		if(ans % 2 == 0){//注意从0开始,还有就是整数/2的小树部分要么是.00,要么就是.50 
			printf("%lld.00\n",ans/2);
		}else{
			printf("%lld.50\n",ans/2);
		}
	}
	
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值