zoukankan      html  css  js  c++  java
  • #4789. 啊孤独感放辣椒

    题目描述

    $n$ 堆石子,第 $i$ 堆有 $a_i$ 个石子。将 $n$ 堆石子合并成三堆,使得这三堆的极差最小。

    数据范围

    $n le 24,a_i le 10^9$ 。

    题解

    考虑折半搜索,考虑如何将两边的三元组合并得到答案。

    考虑两边的三元组分别为 $(a_1,b_1,c_1)$ 和 $(a_2,b_2,c_2)$ ,那么将它们合并后为 $(a_1+a_2,b_1+b_2,c_1+c_2)$ ,为了方便我们令 $a_1+a_2 ge b_1+b_2 ge c_1+c_2$ ,这样这两组的贡献为 $a_1+a_2-c_1-c_2$ 。

    于是我们可以令 $f=a-b,g=b-c$ ,上述条件就变为要求 $f_1+f_2,g_1+g_2 ge 0$ ,求 $f_1+f_2+g_1+g_2$ 最小值,所以我们可以按照 $f$ 排序进行双指针, $g$ 用树状数组维护即可。

    效率 $O(NlogN)$ ,其中 $N=3^{frac{n}{2}}$ 。

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=6e5+5;
    int n,m,a[25],F,G;
    LL b[N],s[N],A=2e18;
    struct O{LL x,y;}f[N],g[N];
    void dfs(int x){
        if (x>m){
            if (m<n)
                f[++F]=(O){s[0]-s[1],s[1]-s[2]};
            else g[++G]=(O){s[0]-s[1],s[1]-s[2]};
            return;
        }
        for (int i=0;i<3;i++)
            s[i]+=a[x],dfs(x+1),s[i]-=a[x];
    }
    bool cmp(O x,O y){return x.x<y.x;}
    #define lb(z) lower_bound(b+1,b+m+1,z)-b
    void upd(int x,LL v){
        for (;x;x-=x&-x) s[x]=min(s[x],v);
    }
    LL qry(int x){
        LL v=2e18;
        for (;x<=m;x+=x&-x) v=min(v,s[x]);
        return v;
    }
    int main(){
        cin>>n;
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        m=n/2;dfs(1);m=n;dfs(n/2+1);
        for (int i=1;i<=G;i++) b[i]=g[i].y;
        sort(b+1,b+G+1);m=unique(b+1,b+G+1)-b-1;
        sort(f+1,f+F+1,cmp);sort(g+1,g+G+1,cmp);
        for (int i=1;i<=m;i++) s[i]=2e18;
        for (int i=1,j=G;i<=F;i++){
            while(j && f[i].x+g[j].x>=0)
                upd(lb(g[j].y),g[j].x+g[j].y),j--;
            A=min(A,qry(lb(-f[i].y))+f[i].x+f[i].y);
        }
        cout<<A<<endl;return 0;
    }
  • 相关阅读:
    屏幕尺寸相关
    关于sqlite的数据库操作
    Service服务
    BroadcastReceiver广播接收器
    将博客搬至CSDN
    win7+WinDbg调试系统内核
    驱动
    驱动开发,走起!!哈哈
    动态链接库DLL
    2013年12月24号感受
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12727363.html
Copyright © 2011-2022 走看看