[二分答案]p1m2

Problem Description

度度熊很喜欢数组!!

我们称一个整数数组为稳定的,若且唯若其同时符合以下两个条件:

1. 数组里面的元素都是非负整数。
2. 数组里面最大的元素跟最小的元素的差值不超过 1

举例而言,[1,2,1,2]

是稳定的,而 [−1,0,−1]

跟 [1,2,3]

都不是。

现在,定义一个在整数数组进行的操作:

* 选择数组中两个不同的元素 a

以及 b

,将 a

减去 2

,以及将 b

加上 1

举例而言,[1,2,3]

经过一次操作后,有可能变为 [−1,2,4]

或 [2,2,1]

现在给定一个整数数组,在任意进行操作后,请问在所有可能达到的稳定数组中,拥有最大的『数组中的最小值』的那些数组,此值是多少呢?

Input

输入的第一行有一个正整数 T

,代表接下来有几组测试数据。

对于每组测试数据:
第一行有一个正整数 N


接下来的一行有 N

个非负整数 xi

,代表给定的数组。

* 1≤N≤3×105

* 0≤xi≤108

* 1≤T≤18

* 至多 1

组测试数据中的 N>30000

Output

对于每一组测试数据,请依序各自在一行内输出一个整数,代表可能到达的平衡状态中最大的『数组中的最小值』,如果无法达成平衡状态,则输出 −1

Sample Input

2
3
1 2 4
2
0 100000000

Sample Output

2
33333333

思路:求最大的最小值,很明显是二分答案;难点在于怎么判断当前枚举的答案是否可行;可以证明(在这我就不证了,可以自己证明),对于当前答案x,计算出a数组中比x小的数变成x需要加1多少次,计算出比x大的数变成x或x+1需要减2多少次,若前者小于等于后者,则当前x是可以达到的;这也同时证明了,答案是单调的,即x可行那0~x-1都可行;

AC代码:

#include <iostream>
#include<cstdio>
#include<algorithm>
typedef long long ll;
using namespace std;

ll n,a[300010];

bool ok(ll x){
  ll sub=0,add=0;
  for(ll i=1;i<=n;i++) {
    if(a[i]<x) add+=(x-a[i]);
    else if((a[i]-x)%2==0) sub+=(a[i]-x)/2;
    else sub+=(a[i]-x-1)/2;
  }
  return sub>=add;
}

int main()
{
    ll t;scanf("%lld",&t);
    while(t--){
        scanf("%lld",&n);
        for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
        sort(a+1,a+1+n);
        ll l=a[1],r=a[n];
        while(l<=r){
            ll mid=(l+r)/2;
            if(ok(mid)) l=mid+1;
            else r=mid-1;
        }
        printf("%lld\n",r);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lllxq/p/9488762.html

时间: 2024-08-01 16:30:12

[二分答案]p1m2的相关文章

hdu6383 p1m2(二分答案)

p1m2 题目传送门 解题思路 因为x都是非负数,且每一次操作其实就是把总和减少了1,所以可以得出最后都可以到达稳定.最后稳定的数的下界是0,最大也不会超过其初始数的最大值,所以可以用二分答案来求解.每次二分,我们统计要到达出来的二分值,每个数进行上升操作的次数总和以及下降次数的总和.如果上升次数大于下降次数,说明这个答案偏大了则r=mid-1,如果上升次数小于下降次数,由于答案是要求稳定后的最小值,而我们计算是使所有数都变得一样,所以下降次数其实是可以大于上升次数的,所以此时和相等时一样,都是

百度之星2018初赛Bt4 P1m2(二分答案)

src:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=826&pid=1004 可以用某值来判断是否满足题意时 可以用二分答案的方法! 代码: #include<bits/stdc++.h> using namespace std; #define per(i,a,b) for(int i=a;i <= b;i++) #define Max(a,b) a=max(a,b) #define Min(

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

HDU3081Marriage Match II(二分答案+并查集+最大流SAP)经典

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2507    Accepted Submission(s): 856 Problem Description Presumably, you all have known the question of stable marriage match. A

Codeforce 371C Hamburgers (二分答案)

题目链接 Hamburgers 二分答案,贪心判断即可. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define LL long long 7 8 char str[1010]; 9 LL len; 10 LL b, c, s, nb, nc, ns, pb, pc, ps; 11 LL money; 12 13 bool

POJ 3080 Blue Jeans(后缀数组+二分答案)

[题目链接] http://poj.org/problem?id=3080 [题目大意] 求k个串的最长公共子串,如果存在多个则输出字典序最小,如果长度小于3则判断查找失败. [题解] 将所有字符串通过拼接符拼成一个串,做一遍后缀数组,二分答案,对于二分所得值,将h数组大于这个值的相邻元素分为一组,判断组内元素是否覆盖全字典,是则答案成立,对于答案扫描sa,输出第一个扫描到的子串即可. [代码] #include <cstdio> #include <cstring> #inclu

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]

IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) 二分答案 + 网络流

这道题的意思是给你一个有向图, 每条边上有一个最大载重量, 现在有x头牛要从顶点1走向顶点n, 每头牛要载的重量都是一样的, 问你最多能载多少的重量? 可以二分答案, 算出每头牛的载重, 然后修改边权, 跑一次最大流即可判断当前答案是否正确, 二分答案即可, 注意由于原始边权/每头牛的载重量可能会很大, 因此我们在修改边权时应该注意这一点,将边权的最大值控制在1000000之内, 防止溢出, 代码如下: #include <bits/stdc++.h> using namespace std;

BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流

题目大意:给定n个男生和n个女生,一些互相喜欢而一些不.举行几次舞会,每次舞会要配成n对.不能有同样的组合出现.每一个人仅仅能与不喜欢的人跳k次舞,求最多举行几次舞会 将一个人拆成两个点.点1向点2连一条流量为k的边.两个人若互相喜欢则点1之间连边,不喜欢则点2之间连边 对于每个要验证的x值 将每个人的点1向源或汇连一条流量为x的边 然后二分答案跑最大流就可以 #include<cstdio> #include<cstring> #include<iostream> #