• 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;
    }
  • 相关阅读:
    redis你要知道的事
    Nginx七层负载均衡的几种调度算法
    JQuery的父、子、兄弟节点选择器
    laravel通用和万能路由
    jquery竖向企业组织结构图
    phpexcel功能操作
    animatext.js使用介绍
    Centos firewalld开放端口
    获取微信accesstoken并文件缓存方式
    css处理文字不换行、换行截断、溢出省略号
  • 原文地址:https://www.cnblogs.com/dishu/p/4314124.html
Copyright © 2020-2023  润新知