首页 > 其他分享 >题解 P7640 [BalticOI 2006 Day 2] CITY PLANNING

题解 P7640 [BalticOI 2006 Day 2] CITY PLANNING

时间:2023-07-17 21:22:27浏览次数:36  
标签:二分 CITY P7640 int 题解 ll cnt up dis

首先我们定义“圈”为与原点距离相等的点集。

. . . 3 . . .
. . 3 2 3 . .
. 3 2 1 2 3 .
3 2 1 0 1 2 3
. 3 2 1 2 3 .
. . 3 2 3 . .
. . . 3 . . .

暴力:

把圈放到堆里,然后每次取出代价最小的一圈,修改当前圈的楼层,向外圈拓展。

正解:

考虑二分。

如果是二分最终答案,我们会发现不好做,所以我们二分所有住户的代价的最大值,即 \(c_i+dis \cdot t\)(显然是具有单调性的)。

check 函数:由于圈的总数是 \(\sqrt{n}\) 级别的,所以可以直接枚举,对于每一圈可以二分出楼层的最大值,然后增加住户总数,最后 return cnt >= n

我们二分出可行与不可行的分界点,然后最终答案只需要在分界点的代价的基础上加上一些增量就行了。

具体看代码吧。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
ll n, t, k, c[N], sum[N], cnt = 0, ans = 0, a[N];
bool check(ll up) {
	cnt = 0; ans = 0;
	memset(a, 0, sizeof(a));
	for (ll i = 1;; ++i) {
		ll dis = (i - 1) * t;
		int p = upper_bound(c + 1, c + k + 1, up - dis) - c - 1; //二分出第i圈的最大楼层 
		if (p < 1) break;
		a[i] = p;
		ans += i * 4 * p * dis + sum[p] * i * 4;
		cnt += i * 4 * p;
		if (cnt >= n) return true;
	}
	return false;
}
int main() {
	ios::sync_with_stdio(false); cout.tie(0); cout.tie(0);
	cin >> n >> t >> k;
	for (int i = 1; i <= k; ++i) cin >> c[i], sum[i] = sum[i - 1] + c[i]; 
	ll l = 1, r = 1e18;
	while (r - l > 2) { //二分住户代价最大值 
		ll mid = (l + r) / 2;
		if (check(mid)) r = mid;
		else l = mid;
	}
	ll up;
	for (ll i = r; i >= l; --i) {
		if (!check(i)) { //分界点 
			up = i + 1;
			break;
		}
	}
	int i, p;
	for (i = 1;; ++i) { //计算增量 
		ll dis = (i - 1) * t;
		p = upper_bound(c + a[i] + 1, c + k + 1, up - dis) - c - 1;
		if (p <= a[i]) continue; //不能写成break! 
		if (cnt + i * 4 > n) break;
		ans += i * 4 * (c[p] + dis);
		cnt += i * 4;
	}
	ans += (n - cnt) * (c[p] + (i - 1) * t);
	cout << ans << endl;
	return 0;
}

标签:二分,CITY,P7640,int,题解,ll,cnt,up,dis
From: https://www.cnblogs.com/HQJ2007/p/17561251.html

相关文章

  • 题解 P7250 [BalticOI 2012 Day1] 山峰
    通过观察,可以发现此题和最小生成树十分相似(两个地点之间途经的最小值最大)。于是可以考虑这么做:通过bfs将每一个块预处理出来,并记录其编号、高度、类型(是否为高地)以及边缘的点。将每一个块按高度从大到小排序。依次枚举每个块:对于当前要处理的块,枚举其边界的所有点,......
  • 题解 AT3726 [ARC087B] FT Robot
    首先可以观察到一个非常重要的性质:对于一次前进的操作,如果前面有奇数次转向,则走上下,否则走左右。(当然如果一开始就前进就只能走右)于是我们可以将其拆成许多的“块”,并分成两类,即前进方向为左右还是上下。然后对于两个维度分别dp。\(f_{i},_{j}=f_{i-1},_{j-val}\|\f_{i-......
  • Charles抓取https请求及常见问题解决
    一、背景APP测试的时候,通常都需要通过抓包工具抓取各类请求,查看接口的入参、返回值等,用于分析定位问题。常用的抓包工具有fiddler、charles等,抓取http的请求比较简单,https的请求稍显复杂。由于更喜欢charles的页面风格,本篇文章主要介绍以下两点:1、Charles如何抓取电脑端和手机端的......
  • CF1808C Unlucky Numbers 题解
    可以证明答案是\(l\)或\(r\)的一段前缀,拼上后面全部相同的一段字符\(d\),证明方式类似数位dp。能够自由填的数字一定是相等的,这样不会影响幸运值。前面那些不能自由填写的,就是\(l\)或\(r\)的一段前缀。假如不是\(l\)或\(r\)的一段前缀,必然填写相等的更好,而这种情况已......
  • P7809 [JRKSJ R2] 01 序列 题解
    前言传送门blog思路Problem1问题一问的是最长不下降子序列的长度,在一个$01$串中的最长不下降子序列,总共有三种$000\dots$,$000\dots111\dots$和$111111\dots$。可以把找到以上三种最长不下降子序列问题变为:$$\max^r_{i=l}(\sum_{j=l}^i[a_j=0])+(\sum_{j=i+1}^......
  • P7333 [JRKSJ R1] JFCA 题解
    前言传送门blog思路首先看数据范围$10^5$,$O(n\log_2n)$可以过,自然想到二分。二分具有单调性,那么如何确保整个$a$序列按顺序排列呢?我们可以使用st表维护区间最大值,如果在这个距离中已经有了$a_i\geb_j$那么最大值一定指向的是新加入进来的那个值,否则在之前二分就......
  • P8708 [蓝桥杯 2020 省 A1] 整数小拼接 题解
    前言传送门blog思路这种选出两个数拼接在一起的题,一看就可以使用two-point,我们使用$l$和$r$分别从最大的和最小的开始搜索,进行两次。以$l$为头,$r$为尾。以$r$为头,$l$为尾。如何比较大小呢?我们可以先去做宇宙总统这道题。首先排序的$cmp$:boolcmp(strin......
  • UVA10791 最小公倍数的最小和 Minimum Sum LCM 题解
    前言长沙市一中8机房0714模拟测1。传送门blog思路本题思路,首先我们先看$\operatorname{lcm}$,明显要使得这些数的$\operatorname{lcm}=n$那么我们就需要所有的数的质因子必须包含$n$的质因子。若$1\lea,b$,则$a\timesb\gea+b$,所以我们就有了策略。将同一个质因......
  • P9451 [ZSHOI-R1] 新概念报数 题解
    目录DescriptionSolutionCodeDescription在此题中,对于一个数\(x\),若\(\texttt{popcount}(x)\geq3\)(即\(x\)在二进制下\(\texttt{1}\)的个数大于等于三时),那它是非法的,否则其为合法的。给定\(T\)个数,如果当前的数\(x\)是非法的,则输出No,Commander,否则输出第一个大于......
  • requests.exceptions.ProxyError问题解决方法
    出现这个问题是因为你系统上在使用代理,然后你的代理又是规则匹配的。https://stackoverflow.com/questions/36906985/switch-off-proxy-in-requests-library3种解决方法:headers={"User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64;rv:109.0)Gecko/20100101Fi......