CodeForces 140F || Codeforces Round #100 F. New Year Snowflake

题目链接:http://codeforces.com/problemset/problem/140/F

大意:给你n个点,你可以最多删除k个(可以不删),在所有的删法中,删完之后的所有点如果以坐标系上某一个点中心对称,输出所有这样子的中心点。

数据范围:n :2e5, k : 10

解题思路:把所有点按横坐标为第一优先级,纵坐标为第二优先级,从小到大排序。然后two pointers枚举区间(区间左端点左边的以及右端点右边的都设为要删掉的),然后check在规定的次数内删这个区间中间的点能不能达到题目要求,能达到就把中心点存下来。

解释几个细节:

1,如何check。因为已经有了区间的l, r,那么这时候枚举的中心点自然就是point[l], point[r]的中点,然后就一对一对地check啦,不符合就删掉,最后比较删的次数cnt和k就知道合不合法了;

2,时间复杂度。其实很显然了,枚举是k ^ 2的,check是O(n)的,所以复杂度O(n * k ^ 2),轻松跑过;

3,这个tow pointers是否不重不漏。是的(其实写的是我的思考过程。。)

 

AC Code:

//My Conquest Is the Sea of Stars.
#pragma GCC diagnostic error "-std=c++11"
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define endl "\n"
#define fi first
#define se second
#define gcd __gcd
#define pb push_back
#define mp make_pair
#define lowbit(x) x & (-x)
#define PII  pair<int, int> 
#define all(x) x.begin(), x.end()
#define rep(i, a, b) for(int i = a; i <= (b); i++)
#define Rep(i, a, b) for(int i = a; i >= (b); i--)
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)2e5 + 5;
const ll INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;

struct pt {
	int x, y;
	bool operator < (const pt &p) const {return mp(x, y) < mp(p.x, p.y);}
	bool operator == (const pt &p) const {return x == p.x && y == p.y;};
	pt operator + (pt p) {return {x + p.x, y + p.y};}
}a[maxn];

int n, k;
set<pt> ans;

int main()
{
	scanf("%d %d", &n, &k);
	rep(i, 1, n) scanf("%d %d", &a[i].x, &a[i].y);
	if(k >= n) return 0 * puts("-1");
	sort(a + 1, a + n + 1);
	rep(l, 1, min(n, k + 1)){
		Rep(r, n, max(n - k, l)){
			int cnt = l - 1 + n - r;
			if(cnt > k) continue;
			pt center = a[l] + a[r];
			int j = r;
			rep(i, l, j){
				while(i < j && center < a[i] + a[j]){
					cnt++;
					j--;
				}
				if(a[i] + a[j] == center) j--;
				else cnt++;
			}
			if(cnt <= k) ans.insert(center);
		}
	}
	printf("%d\n", ans.size());
	for(auto p : ans){
		printf("%.7f %.7f\n", p.x / 2.0, p.y / 2.0);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值