【二分答案】【中位数】codeforces 394 bun

bun
Description
因为体育老师很喜欢等差数列,所以他要求学生们站队必须按身高站成等差数列。
但是有些班级的学生无论如何也无法排成等差数列,于是体育老师从食堂买来了两种神
奇的面包。吃一个第一种面包可以使身高增 1,吃一个第二种面包可以使身高减 1。
你的任务是,对于某个班级,帮助老师安排哪些同学食用多少面包。考虑到学生的身体
健康,体育老师希望吃面包最多的学生吃的面包数量尽量少。
Input Format
第一行一个正整数 n,表示学生的数目。
第二行是长度为 n 的整数序列 a, a[i]表示第 i 个学生的身高。由于体育老师使用的奇怪
的身高单位,学生身高可能是负数。可以打乱顺序重新排列。
Output Format
第一行一个整数,表示吃面包最多的学生吃的面包数量。
第二行两个整数,分别表示等差数列的首项和公差,公差不能为负。
如果有多解,输出公差最小的方案。如果还有多解,输出首项最小的方案。
Sample Input (1)
5
-3 -4 -2 -3 3
Sample Output (1)
2
-3 1
Sample Input (2)
5
2 -3 -1 -4 3
第 8 页 共 8 页
Sample Output (2)
1
-4 2
Hint
对于 30%的数据,n<=100,a[i]的绝对值<=1000。
对于 60%的数据,n<=1000,a[i]的绝对值<=100000。
对于 100%的数据,n<=100000,a[i]的绝对值<=1000000。

<法一>记f1为当前需要吃的增高面包的最大的量,f2为当前需要吃的减低面包最大的量。

考虑暴力的情况,枚举公差d,我们可以通过计算f1、f2,再取中位数的方式得到当前的最优首项。

我们把每个d对应的f1、f2打出表来,就可以发现,f1单调递减,f2单调递增,它们两个相交的位置就是答案,二分即可(怕写错,写了分块答案)。

<法二>orz faebdc,我们在枚举d的时候,易发现,d最大不会超过4*max(a[i])/n,否则还不如把a全变0更优,因此暴力就好啦~

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 100001
int n,a[N],ans=2147483647,b[N],f1,f2,D,X0;
int main()
{
	scanf("%d",&n);
	if(n<=1000){
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	int lim=30000000/n;
	f1=f2=0;
	for(int i=1;i<=n;++i)
	  {
	  	b[i]=a[1]-a[i];
	  	if(b[i]>0) f2=max(f2,b[i]);
		else f1=max(f1,-b[i]);
	  }
	if(ans>((f1+f2+1)>>1))
	  {
	  	ans=((f1+f2+1)>>1);
	  	D=0;
	  	if(f1<f2)
	  	  X0=a[1]-(((f1+f2+1)>>1)-f1);
	  	else
	  	  X0=a[1]+(f1-((f1+f2+1)>>1));
	  }
	for(int d=1;d<=lim;++d)
	  {
	  	f1=f2=0;
	  	for(int i=2;i<=n;++i)
	  	  {
	  	  	b[i]+=(i-1);
	  	  	if(b[i]>0) f2=max(f2,b[i]);
			else f1=max(f1,-b[i]);
	  	  }
	  	if(ans>((f1+f2+1)>>1))
	  	  {
	  	  	ans=((f1+f2+1)>>1);
	  		D=d;
		  	if(f1<f2)
	  		  X0=a[1]-(((f1+f2+1)>>1)-f1);
	 	 	else
	 	 	  X0=a[1]+(f1-((f1+f2+1)>>1));
	  	  }
	  }
	printf("%d\n%d %d\n",ans,X0,D);
	return 0;
	}
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	f1=f2=0;
	for(int i=1;i<=n;++i)
	  {
	  	b[i]=a[1]-a[i];
	  	if(b[i]>0) f2=max(f2,b[i]);
		else f1=max(f1,-b[i]);
	  }
	if(ans>((f1+f2+1)>>1))
	  {
	  	ans=((f1+f2+1)>>1);
	  	D=0;
	  	if(f1<f2)
	  	  X0=a[1]-(((f1+f2+1)>>1)-f1);
	  	else
	  	  X0=a[1]+(f1-((f1+f2+1)>>1));
	  }
	if(f2>=f1)
	  {
	  	printf("%d\n%d %d\n",ans,X0,D);
	  	return 0;
	  }
	int sz=sqrt(n),last=0;
	for(int i=1;last<=n;i+=sz)
	  {
	  	f1=f2=0;
	  	for(int j=2;j<=n;++j)
	  	  {
	  	  	b[j]+=(i==1?1:sz)*(j-1);
	  	  	if(b[j]>0) f2=max(f2,b[j]);
			else f1=max(f1,-b[j]);
	  	  }
	  	if(ans>((f1+f2+1)>>1))
	  	  {
		  	ans=((f1+f2+1)>>1);
		  	D=i;
		  	if(f1<f2)
		  	  X0=a[1]-(((f1+f2+1)>>1)-f1);
		  	else
		  	  X0=a[1]+(f1-((f1+f2+1)>>1));
		  }
	  	if(f2>=f1)
	  	  {
	  	  	for(int j=2;j<=n;++j)
	  	  	  b[j]-=(i==1?1:sz)*(j-1);
	  	  	for(int j=last+1;j<=i;++j)
	  	  	  {
	  	  	  	f1=f2=0;
	  	  		for(int k=2;k<=n;++k)
	  	 	  	  {
	  	  			b[k]+=(k-1);
	  	 	 		if(b[k]>0) f2=max(f2,b[k]);
					else f1=max(f1,-b[k]);
	  			  }
	  			if(ans>((f1+f2+1)>>1))
	  			  {
	  				ans=((f1+f2+1)>>1);
	  				D=j;
	  				if(f1<f2)
	  	  			  X0=a[1]-(((f1+f2+1)>>1)-f1);
	  				else
	  	  			  X0=a[1]+(f1-((f1+f2+1)>>1));
	  			  }
	  	  	  	if(f2>=f1)
			      {
			  	    printf("%d\n%d %d\n",ans,X0,D);
			  	    return 0;
			      }
	  	  	  }
	  	  }
	  	last=i;
	  }
	return 0;
}
时间: 2024-10-07 08:45:05

【二分答案】【中位数】codeforces 394 bun的相关文章

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

Codeforces Round #256 (Div. 2)D 二分答案

D. Multiplication Table time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Bizon the Champion isn't just charming, he also is very smart. While some of us were learning the multiplication tabl

Educational Codeforces Round 3:D. Gadgets for dollars and pounds(二分答案+贪心)

看了菊苣的理解才知道怎么写..根本没思路啊一开始... 天数肯定在1~n之间,二分答案. 可以用保存前i天的最低美元和英镑汇率,没有规定哪天买,每天也没有购买数量限制,所以二分出一个答案mid的后,就在前mid天中汇率最低的时候一次性购入最便宜的就行了,judge一下总花费 打印答案的时候以ans为结果,再模拟一遍就好 #include"cstdio" #include"queue" #include"cmath" #include"s