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;
    }
  • 相关阅读:
    选择结构(一)
    媒体元素与表单
    变量、数据类型和运算符
    通俗易懂--快速入门Vue--4
    通俗易懂--快速入门Vue--2
    通俗易懂--快速入门Vue--3
    通俗易懂--快速入门Vue--1
    Vue之v-model
    Vue基础篇--5列表渲染v-for
    Vue基础篇--7表单输入绑定input
  • 原文地址:https://www.cnblogs.com/dishu/p/4314124.html
Copyright © 2011-2022 走看看