zoukankan      html  css  js  c++  java
  • poj 2785 4 Values whose Sum is 0 折半枚举

    题目链接:http://poj.org/problem?id=2785

    枚举的一般思路就是先把所有的状态枚举出来 最后一次性判断该状态合法不合法

    而折半枚举的思想是

    先枚举一半的状态 把他们的状态存起来 排序

    然后再枚举剩下一般 用目标反推前一半的期望状态 接下来在前一半的结果数组中查找是否有相应结果

    之所以能优化是因为结果数组有序 就可以用二分搜索

    复杂度从O(n^2 * n^2) 降到 O(n^2 * log(n^2))即(O(n^2 * log n))

    二分搜索的一个技巧

    在有序数组中用二分查找方式统计有多少值为CD的元素的写法:

    res += upper_bound(cd, cd + n*n, CD) - lower_bound(cd, cd + n*n, CD);

    类似的问题还有“超大的01背包问题”

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <set>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> P;
    
    const int maxn = 5000;
    
    int a[maxn], b[maxn], c[maxn], d[maxn];
    int cd[maxn * maxn];
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
    
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
            scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);
    
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                cd[i*n + j] = c[i] + d[j];
    
        sort(cd, cd + n * n);
    
        ll res = 0;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                int CD = -(a[i] + b[j]);
                res += upper_bound(cd, cd + n*n, CD) - lower_bound(cd, cd + n*n, CD);
            }
        }
    
        printf("%lld
    ", res);
    
        return 0;
    }
  • 相关阅读:
    安全工具-Arachni
    Python读取本地文档内容并发送邮件
    Linux好用的工具命令
    kali 安装google chrome浏览器(离线手动)
    安全工具-Sparta
    安全工具-Hydra
    当年的程序员,如今已是父母,七个方法让孩子爱上学习!
    一个网站SEO优化方案
    发现2017年最好的CSS框架
    怎么样加快JavaScript加载和执行效率
  • 原文地址:https://www.cnblogs.com/dishu/p/4314124.html
Copyright © 2011-2022 走看看