zoukankan      html  css  js  c++  java
  • POJ

    条件a+b == d-c,O(n*n)枚举出所有的形如a+b的和,然后从大到小枚举d,在枚举c,二分找d-c。

    主要是要用容斥排除c和d出现在和中,详细的过程见注释。

    复杂度为O(n^2log(n^2))。

    /*********************************************************
    *            ------------------                          *
    *   author AbyssalFish                                   *
    **********************************************************/
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<cmath>
    #include<numeric>
    using namespace std;
    
    /*
    容斥原理去重复
    左边是枚举出来的,保证不等
    可能出现重复的情况有:
    d 和 c同时出现
    case 1 d+c == d-c -> c == 0
    
    其中一个出现
    前提
    a or b != c or d
    
    case2  a+d == d-c, -> a == -c , 必要条件 a != c -> c != 0 如果不满足这个条件:找到的可能是d == d
    case3  d+b == d-c, -> b == -c
    case 2 3互斥
    
    case4  a+c == d-c, -> a == d-2*c, 必要条件 a != d -> c != 0
    case5  c+b == d-c -> b == d-2*c
    case 4 5互斥
    
    case (2,3,4,5) 1互斥
    */
    
    const int maxn = 1e3, INF = 536870911+5;
    int n;
    int e[maxn+1], tab[maxn*maxn>>1];
    bool vis[maxn];
    
    int solve()
    {
        sort(e,e+n);
        int i, j, a, c, d, k;
        int sz = 0;
        for(i = 1; i < n; i++){
            a = e[i];
            for(j = 0; j < i; j++){
                tab[sz++] = a+e[j];
            }
        }
        sort(tab,tab+sz);
        e[n] = e[n]-1;
        for(j = 0; j < n; j++) {
            c = -e[j];
            vis[j] = (*lower_bound(e,e+n,c) == c); // c == 0 || -c == a or b
        }
        tab[sz+1] = tab[sz] = tab[sz-1]-1;
        for(i = n; i--; ){
            d = e[i];
            for(j = 2; j < n; j++)if(i!=j){
                c = e[j];
                a = d-c;
                k = lower_bound(tab,tab+sz,a)-tab;
                if(c){
                    if(vis[j]) k++;
                    if(*lower_bound(e,e+n,a-c) == a-c) k++;
                }
                else k++;
                if(a == tab[k]) return d;
            }
        }
        return INF;
    }
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        while(scanf("%d",&n),n){
            for(int i = 0; i < n; i++) scanf("%d", e+i);
            int res = solve();
            if(res < INF) printf("%d
    ", res);
            else puts("no solution");
        }
        return 0;
    }

     伪二分O(n^3) ???

    int solve()
    {
        sort(e,e+n);
        int i, j, sum, lb, ub, tsum;
    
        for(i = n; i--; ){
            for(j = 2; j < n; j++)if(i!=j){
                sum = e[i]-e[j];
                for(lb = 0,ub = j-1; lb < ub; ){ //状态是DAG
                    tsum = e[lb]+e[ub];
                    if(tsum == sum) return e[i];
                    tsum > sum ? ub--:lb++; //O(n)
                }
            }
        }
        return INF;
    }
  • 相关阅读:
    JS算法练习一
    jquery抖动的按钮
    CSS3教程:box-sizing属性的理解border、padding与容器宽度的关系
    鼠标hover事件
    object 插入元素,插入HTML页面
    点击展开点击收起
    IE支持CSS3圆角
    登录事件,鼠标点击输入框隐藏默认值事件
    复制 动态文本按钮
    凯撒密码、GDP格式化输出、99乘法表
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4975779.html
Copyright © 2011-2022 走看看