zoukankan      html  css  js  c++  java
  • 洛谷 P4799 [CEOI2015 Day2]世界冰球锦标赛

    Description

    P4799 [CEOI2015 Day2]世界冰球锦标赛

    Solution

    折半搜索好题。

    发现到 (n leq 2 ^ {20}) 时,可以直接爆搜出答案,而数据范围是 (n leq 2 ^ {40}),所以我们考虑折半搜索。

    具体来说,把前 20 场和后 20 场分别爆搜出答案。

    如何爆搜呢?既然是要爆搜,那么爆搜就完了,枚举到一场比赛时,看或者不看都搜索一遍即可(可以看下方代码理解一下)。

    搜索完之后如何合并呢?

    这个也很简单,我们假设前 20 场存到了 (a) 数组中,后 20 场存到了 (b) 数组中。

    我们对 (b) 数组从小到大排序。枚举 (a) 数组,然后在 (b) 数组中二分答案,查找有多少汾河条件的观看方式,累加即可。

    时间复杂度 (O(2^{frac{n}{2}} + nlog_n))

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    
    using namespace std;
    
    ll n, m, cnta, cntb;
    ll t[50], a[1 << 21], b[1 << 21];
    
    inline void dfs(ll l, ll r, ll sum, ll a[], ll &cnt){
    	if(sum > m) return;
    	if(l > r){
    		a[++cnt] = sum;
    		return;
    	}
    	dfs(l + 1, r, sum + t[l], a, cnt);
    	dfs(l + 1, r, sum, a, cnt);
    }
    
    signed main(){
    	scanf("%lld%lld", &n, &m);
    	for(ll i = 1; i <= n; i++)
    		scanf("%lld", &t[i]);
    	ll mid = n >> 1;
    	dfs(1, mid, 0, a, cnta);
    	dfs(mid + 1, n, 0, b, cntb);
    	sort(a + 1, a + 1 + cnta);
    	sort(b + 1, b + 1 + cntb);
    	ll ans = 0;
    	for(ll i = 1; i <= cnta; i++)
    		ans += upper_bound(b + 1, b + 1 + cntb, m - a[i]) - b - 1;
    	printf("%lld
    ", ans);
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15378232.html

  • 相关阅读:
    vue+vuex构建单页应用
    vue如何做分页?
    cookie和session的原理机制
    经常遇到js的面试题
    CSS浏览器兼容性问题解决方法总结
    前端性能优化----yahoo前端性能团队总结的35条黄金定律
    bom对象
    正则表达式
    JavaScript
    常见浏览器bug以及解决方法
  • 原文地址:https://www.cnblogs.com/xixike/p/15378232.html
Copyright © 2011-2022 走看看