Electric Charges CodeForces - 623C (二分答案)

大意: 平面上n个点每个点坐标为(x,0)或(0,y), 求任意两点距离平方最大值的最小值.

二分答案, 转化为判定最大值是否<=e, 按$x$排序后, 因为固定左端点, $y$绝对值的最大值是跟右端点单调的, 滑动一个长度平方不超过e的区间, 同时保证右端点$x$的绝对值不超过左端点, 这样对于左端点在$x$轴的情况一定是最优的, 同样再固定右端点倒序处理正半轴的情况.

#include <iostream>
#include <random>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl ‘\n‘
#define DB(a) ({REP(__i,1,n) cout<<a[__i]<<‘ ‘;hr;})
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
inline int rd() {int x=0;char p=getchar();while(p<‘0‘||p>‘9‘)p=getchar();while(p>=‘0‘&&p<=‘9‘)x=x*10+p-‘0‘,p=getchar();return x;}
//head

#ifdef ONLINE_JUDGE
const int N = 1e6+10;
#else
const int N = 111;
#endif

int n;
pii a[N];
int Lmin[N], Lmax[N], Rmin[N], Rmax[N];

ll sqr(ll x) {return x*x;}
ll ans = 1e18;
int chk(ll e) {
    if (ans<=e) return 1;
	int now = 1;
	ll ans = 1e18;
	REP(i,1,n) {
		if (a[i].x>0) break;
		while (now<n&&sqr(a[now+1].x-a[i].x)<=e&&abs(a[now+1].x)<=abs(a[i].x)) ++now;
		while (abs(a[now].x)>abs(a[i].x)) --now;
		int U = -1e9, D = 1e9;
		if (i>1) U=max(U,Lmax[i-1]),D=min(D,Lmin[i-1]);
		if (now<n) U=max(U,Rmax[now+1]),D=min(D,Rmin[now+1]);
		ans = min(ans, max(sqr(U-D),max(sqr(U),sqr(D))+max(sqr(a[i].x),sqr(a[now].x))));
	}
	now = n;
	PER(i,1,n) {
		if (a[i].x<0) break;
		while (now>1&&sqr(a[now-1].x-a[i].x)<=e&&abs(a[now-1].x)<=abs(a[i].x)) --now;
		while (abs(a[now].x)>abs(a[i].x)) ++now;
		int U = -1e9, D = 1e9;
		if (i<n) U=max(U,Rmax[i+1]),D=min(D,Rmin[i+1]);
		if (now>1) U=max(U,Lmax[now-1]),D=min(D,Lmin[now-1]);
		ans = min(ans, max(sqr(U-D),max(sqr(U),sqr(D))+max(sqr(a[i].x),sqr(a[now].x))));
	}
	return ans<=e;
}

int main() {
	scanf("%d", &n);
	REP(i,1,n) scanf("%d%d", &a[i].x,&a[i].y);
	sort(a+1,a+1+n);
	Lmin[1]=Lmax[1]=a[1].y;
	REP(i,2,n) {
		Lmin[i]=min(Lmin[i-1],a[i].y);
		Lmax[i]=max(Lmax[i-1],a[i].y);
	}
	Rmin[n]=Rmax[n]=a[n].y;
	PER(i,1,n-1) {
		Rmin[i]=min(Rmin[i+1],a[i].y);
		Rmax[i]=max(Rmax[i+1],a[i].y);
	}
	ll l = 0, r = min(sqr(Lmin[n]-Lmax[n]),sqr(a[1].x-a[n].x));
	ans = r;
	while (l<=r) {
		if (chk(mid)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%lld\n", ans);
}

原文地址:https://www.cnblogs.com/uid001/p/10798588.html

时间: 2024-11-15 15:53:50

Electric Charges CodeForces - 623C (二分答案)的相关文章

codeforces 359D 二分答案+RMQ

上学期刷过裸的RMQ模板题,不过那时候一直不理解>_< 其实RMQ很简单: 设f[i][j]表示从i开始的,长度为2^j的一段元素中的最小值or最大值 那么f[i][j]=min/max{d[i][j-1], d[i+2^j-1][j-1]} RMQ的ST算法: 1 void ST() //初始化 2 { 3 memset(RMQ,1,sizeof(RMQ)); 4 5 for(int i=1;i<=n;i++) 6 RMQ[i][0]=a[i]; 7 for(int j=1;(1<

Codeforces 1132D(二分答案+堆)

题面 传送门 分析 二分答案,考虑如何判定 可以用贪心的方法,每次找最快没电的电脑,在没电前1单位时间给它充电 正确性显然 实现上可以维护一个堆,存储每个电脑电用完的时刻,每次从堆顶取出最小的一个给它充电.设二分值为mid,对于每个电脑记录它的充电次数num[i],则没电的时间就是\(\lfloor \frac{a_i+num_i\times mid}{b_i} \rfloor+1\) 如果在维护堆的过程中发现当前时间已经超过某个电脑的没电时间,则返回false 代码 #include<iost

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store

Codeforces 700A As Fast As Possible(二分答案)

[题目链接] http://codeforces.com/problemset/problem/700/A [题目大意] 有一辆限载k人速度为v2的车,n个步行速度均为v1的人要通过一段长度为l的距离,每个人只能上车一次,车可以来回走,问所有人到达目的地所需要的最短时间是多少 [题解] 因为车可以载k个人,所以,我们把人k个为一组分成(n+k-1)/k组,记为p吗,设需要的最短时间为t,每个人在车上待的时间为t2,那么可以列方程v1*(t-t2)+v2*t2=l,我们可以发现t2可以用t来表示,

Codeforces Round #425 (Div. 2) Problem C (Codeforces 832C) Strange Radiation - 二分答案 - 数论

n people are standing on a coordinate axis in points with positive integer coordinates strictly less than 106. For each person we know in which direction (left or right) he is facing, and his maximum speed. You can put a bomb in some point with non-n

Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market 二分答案 +排序

Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market 二分答案 +排序 题意 有 a[ i ] 个数 要求选最多的数 使其和不超过 S ,且在此情况下,和最小选最多数情况下 和最小 且 每个数有加成 如果选了 k个数 那么加成后 就是 a[ i ] + k*i ; 题解 二分mid 表示选了个数 加成一下,将加成以后结果排序一下 , 若前 mid数 和大于 s 则此方案不可行 PS 要用 long long ..... 还有 co

Codeforces 460C prsent(二分答案)

//题意:给定N朵花的原先的高度,从左到右排列, //最多浇水m天,每天只能浇一次,每次使得连续的w朵花的高度增长1,问最后最矮的花的高度最高是多少. # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int main() { __int64 n,m,w,l,r,i,m1,sum; __int64 a[200010],b[200010]; while(~

Educational Codeforces Round 21 Problem F (Codeforces 808F) - 最小割 - 二分答案

Digital collectible card games have become very popular recently. So Vova decided to try one of these. Vova has n cards in his collection. Each of these cards is characterised by its power pi, magic number ci and level li. Vova wants to build a deck

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案

There are n people and k keys on a straight line. Every person wants to get to the office which is located on the line as well. To do that, he needs to reach some point with a key, take the key and then go to the office. Once a key is taken by somebo