zoukankan      html  css  js  c++  java
  • [HDU 4261] Estimation

    [题目链接]

             http://acm.hdu.edu.cn/showproblem.php?pid=4261

    [算法]

            首先,有一个结论 :

            | a[1] - k | + | a[2] - k | + ... + | a[n] - k | 当k取(a[1],a[2], ... , a[n])的中位数时,式子的值最小

            考虑动态维护中位数

            我们用一个大根堆和一个小根堆,大根堆中存放前[1..N/2](向上取整)小的数,小根堆中存放[N/2 + 1,N]小的数,还需维护两个变量s1和s2,分别为小根堆中所有数的和和大根堆中所有数的和

            这样,我们就可以预处理出每一段的最小值

            然后,我们用f[i][j]表示前i个数分成j段取得的最小值,有状态转移方程 :

            f[i][j]  = min{ f[k][j - 1] + middle( k + 1,i) ) (其中,middle(k + 1,i)表示[k + 1,i]中每个数与中位数的差值和)

            答案即为f[n][k]

    [代码]

              

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 2010
    #define MAXK 30
    const int INF = 2e9;
    
    int i,j,k,s1,s2,x,y,n,m,middle;
    int a[MAXN],sum[MAXN][MAXN];
    int f[MAXN][MAXK];
    
    struct Sheap
    {
            int tot;
            int a[MAXN];
            inline void clear()
            {
                    tot = 0;
            }
            inline void up(int now)
            {
                    if (now == 1) return;
                    int fa = now >> 1;
                    if (a[now] < a[fa])
                    {    
                            swap(a[now],a[fa]);
                            up(fa);
                    }
            }
            inline void down(int now)
            {
                    int son = now << 1;
                    if (son > tot) return;
                    if (son + 1 <= tot && a[son + 1] < a[son]) son++;
                    if (a[son] < a[now])
                    {
                            swap(a[son],a[now]);
                            down(son);
                    }
            }
            inline void insert(int x)
            {
                    a[++tot] = x;
                    up(tot);
            }
            inline void del()
            {
                    swap(a[1],a[tot]);
                    tot--;
                    down(1);
            }
            inline int getroot()
            {
                    return a[1];
            }
    } S;
    struct Bheap
    {
            int tot;
            int a[MAXN];
            inline void clear()
            {
                    tot = 0;        
            }            
            inline void up(int now)
            {
                    if (now == 1) return;
                    int fa = now >> 1;
                    if (a[now] > a[fa])
                    {
                            swap(a[now],a[fa]);
                            up(fa);
                    }
            }
            inline void down(int now)
            {
                    int son = now << 1;
                    if (son > tot) return;
                    if (son + 1 <= tot && a[son + 1] > a[son]) son++;
                    if (a[son] > a[now])
                    {
                            swap(a[now],a[son]);
                            down(son);
                    }
            }
            inline void insert(int x)
            {
                    a[++tot] = x;
                    up(tot);
            }
            inline void del()
            {
                    swap(a[1],a[tot]);
                    tot--;
                    down(1);
            }
            inline int getroot()
            {
                    return a[1];
            }
    } B;
    
    int main() 
    {
            
            while (scanf("%d%d",&n,&m) && (n || m))
            {
                    for (i = 1; i <= n; i++) scanf("%d",&a[i]);
                    for (i = 1; i <= n; i++)
                    {
                            B.clear();
                            S.clear();
                            sum[i][i] = 0;
                            B.insert(a[i]);
                            s1 = a[i];
                            s2 = 0;
                            for (j = i + 1; j <= n; j++)
                            {
                                    if (B.tot <= (j - i) / 2) 
                                    {
                                            B.insert(a[j]);
                                            s1 += a[j];
                                    } else 
                                    {
                                            S.insert(a[j]);
                                            s2 += a[j];
                                    }
                                    x = B.getroot();
                                    y = S.getroot();
                                    if (x > y)
                                    {
                                            B.del();
                                            s1 -= x;
                                            S.del();
                                            s2 -= y;
                                            S.insert(x);
                                            s2 += x;
                                            B.insert(y);    
                                            s1 += y;    
                                    } 
                                    middle = B.getroot();
                                    sum[i][j]    = middle * B.tot - s1 + s2 - middle * S.tot;
                            }        
                    }        
                    for (i = 1; i <= n; i++)
                    {
                            for (j = 1; j <= m; j++)
                            {
                                    f[i][j] = INF;
                            }
                    }
                    for (i = 1; i <= n; i++) f[i][1] = sum[1][i];
                    for (i = 1; i <= n; i++)
                    {
                            for (j = 2; j <= m; j++)
                            {
                                    for (k = i - 1; k >= 1; k--)
                                    {
                                            f[i][j] = min(f[i][j],f[k][j - 1] + sum[k + 1][i]);
                                    }
                            }
                    }
                    printf("%d
    ",f[n][m]);
            }
            
            return 0;
        
    }
  • 相关阅读:
    多线程的同步锁和死锁
    多线程同步
    oracle11g导出表时会发现少表,空表导不出解决方案
    GET和POST两种基本请求方法的区别
    数据库优化
    JavaScript中的基本数据类型
    Spring Data Jpa简单了解
    单例和多例详解
    jsp九大内置对象
    JavaEE 前后端分离以及优缺点
  • 原文地址:https://www.cnblogs.com/evenbao/p/9357093.html
Copyright © 2011-2022 走看看