牛客网练习赛15__吉姆的奇思妙想

题目描述 

吉姆是个热爱算法竞赛的小朋友,平常的休闲活动就是刷  牛客网 的题目。
当吉姆刷到  wannafly挑战赛12 F.小H和圣诞树  这题时,颇为震惊,因为这是他第一次在wannafly挑战赛上看到作者提供的解答的时间复杂度的式子里含有根号的题目,于是吉姆就开始在网络上搜寻拥有类似时间复杂度解法的问题,并且看到了以下这题:
给你一个有 N 个点 M 条边的无向简单图,请算算此图中有几个三角形。我们称无序的三个点 x,y,z 为三角形,若且唯若 (x,y)、(y,z)、(x,z) 都是此图上的边。
吉姆 想了这个问题七天七夜后,他发现了一件事情:
(1) 对于任一个度数为 d 的点,我们可以用 O(d 2) 的时间复杂度来计算有多少三角形包含这该点。
吉姆 又想了这个问题七天七夜后,他又发现了一件事情:
(2) 对于任一个点,我们可以用 O(M) 的时间复杂度来计算有多少三角形包含该点。
吉姆又再想了这个问题十四天十四夜后,他忽然想到:
(3) 不如就把 (1) 和 (2) 的算法结合在一起!找一个恰当的整数s 若一个点度数小于等于s,就使用(1),否则就使用(2),经过缜密的时间复杂度分析,发现这么做的时间复杂度会是 ,取  ,时间复杂度就会是 。最后再把包含各个点的三角形数全部加起来再除以 3 就是答案了! (因为每个三角形会被算到三次。) (此时间复杂度的详细证明会在今天的题解中解说唷~)
但这个 s 的值究竟要设为多少呢?这就和 (1) 与 (2) 两种方法的执行时间的常系数有关了。
于是,吉姆为了透彻了解这个问题,就假定(1) 和(2) 的常系数分别是a 与b,这意思是:对于一个度数为d 的点,若使用(1),程式的执行时间和a×d 2 成正比;若使用(2),程式的执行时间则和b×M 成正比。
对于一个给定的图,吉姆想要知道对于不同的 a,b,s 的值要取多少比较好,并且求出 s 为该值时程式所需的执行时间!
在这个问题里,我们不会真的给你一个图,只会告诉你边数 M。并对于所有正整数 d,告诉你度数为 d 的点有几个。甚至,题目里给你的图不一定实际上存在的简单图(意即输入可能不是一个合法的简单图的度序列)。
大家好,以上是题目背景。(哈哈哈哈哈嚯嚯嚯嚯~)
给你两个正整数 M, L, 以及两个长度为 L 个正整数序列 deg 1,deg 2,..., deg L 和 freq 1, freq 2,..., freq L
(deg i 和 freq i 对应到 Background 里提到的问题的意思就是:度数为 deg 的点 有 freq 个。)
你要回答 Q 个问题,第 i 个问题会给你 2 个正整数 a i, b i,请找到一个整数 s 使得以下式子(E i) 的值最小:
(此式就是 Background 里提到的程式执行时间的估计函数)

输入描述:

 
 

输入共有 1+L+1+Q 行。 第一行有有两个正整数 M,L。 接下来的 L 行中的第 i 行有两个正整数 degi 和 freqi。 下一行有一个正整数 Q。 最后 Q 行中的第 i 行有两个正整数 ai, bi

输出描述:

对于每个询问都输出一行包含一个整数,代表式子 Ei 的最小值。
示例1

输入

5 4
1 1
2 1
3 1
4 1
5
1 1
3 2
2000 1
1 2000
2000 2000

输出

15
33
20
30
30000

说明

取 s=2 将會有 E1 的最小值:12×1+22×1+5×1+5×1=15。

备注:

1≤M≤10101≤L≤2×1051≤degi,freqi≤10101≤Q≤5×104,1≤ai,bi≤2×103,对于所有 1≤i<L,都有 degi<degi+1
对于所有可能测试数据的答案都能使用 64 bit 有符号整数表示。

思路:可以用三分搜索解;

能用三分搜求极小值的充分条件是:该函数在我们会询问的定义域下,是先严格递减再严格递增。

于是我们来观察看看s = deg[ j ]和 s = deg[ j + 1 ]时,E[ i ]是如何变化的。

结果发现,它的变化量Δj是freg[ j ]*(a[ i ] * deg[ j ]*deg[ j ] - b[ i ]*M),而deg[ j ]是随着j增加而严格递增的序列,故Δj确实是先严格递减再严格递增。

代码:

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int maxn = 2*1e5+7;
ll M;
int L, Q;
ll deg[maxn], freq[maxn];
ll dp_front[maxn], dp_back[maxn];

int main()
{
    memset(dp_front, 0, sizeof(dp_front));
    memset(dp_back, 0, sizeof(dp_back));
    scanf("%lld%d", &M, &L);
    for(int i = 1; i <= L; i++) scanf("%lld%lld", °[i], &freq[i]);
    for(int i = 1; i <= L; i++) dp_front[i] = dp_front[i - 1] + deg[i] * deg[i] * freq[i];
    for(int i = L; i > 0; i--) dp_back[i] = dp_back[i + 1] + M * freq[i];
    scanf("%d", &Q);
    while(Q--) {
        int a, b;
        scanf("%d%d", &a, &b);
        int it = upper_bound(deg + 1, deg + L + 1, (ll)sqrt(b*M/a)) - deg;
        printf("%lld\n", a*dp_front[it - 1] + b*dp_back[it]);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode和牛客网都是在线编程练习平台,供程序员进行算法和编程题目的练习。两个平台有一些区别。 LeetCode是一个以算法为主的平台,题目描述简练,直奔主题,通常使用英文进行描述。LeetCode注重算法思维和解题能力的锻炼,题目更偏向于算法和数据结构的应用。许多人在LeetCode上进行练习,习惯了它的题目风格和解题模式。 而牛客网是一个综合性的在线编程平台,除了算法题,还包括面试题、笔试题、实习生项目等。牛客网的题目描述相对LeetCode来说更加贴近实际场景,有更多的描述和背景信息。这也可能导致牛客网的题目相对较长,需要花费一些时间来阅读和理解。 不同的人对于这两个平台的喜好和适应程度各有差异。有的人可能习惯于LeetCode的简练风格,而对牛客网的题目描述感到吃力;有的人则喜欢牛客网提供的更多背景和场景信息。 总的来说,LeetCode和牛客网都是很好的编程练习平台,可以根据个人的需要和喜好进行选择和使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [LeetCode和牛客网的对比](https://blog.csdn.net/zr1076311296/article/details/51606300)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值