• BZOJ 1112: [POI2008]砖块Klo


    1112: [POI2008]砖块Klo

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1736  Solved: 606
    [Submit][Status][Discuss]

    Description

    N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.

    Input

    第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000

    Output

    最小的动作次数

    Sample Input

    5 3
    3
    9
    2
    3
    1

    Sample Output

    2

    HINT

    原题还要求输出结束状态时,每柱砖的高度.本题略去.

    Source

     
    [Submit][Status][Discuss]

    分析

    对于一段区间,可以知道将高度改为中位数是最优的,因此我们需要做的是维护一个区间的中位数,以及小于中位数的数字之和和大于中位数的数字之和,这个可以平衡树,可以树状数组+二分查找,或者是线段树上二分,甚至是STL set,做法太多……

    代码

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <iostream>
      6 #include <algorithm>
      7 
      8 #define ri register int
      9 
     10 #define lim 10000000
     11 
     12 char *c = new char[lim];
     13 
     14 template <class T>
     15 void read(T &x)
     16 {
     17     x = 0;
     18     
     19     while (*c < '0')++c;
     20     
     21     while (*c >= '0')
     22         x = x*10 + *c++ - '0';
     23 }
     24 
     25 template <class T>
     26 void Min(T &a, T b)
     27 {
     28     if (a > b)a = b;
     29 }
     30 
     31 template <class T>
     32 void Max(T &a, T b)
     33 {
     34     if (a < b)a = b;
     35 }
     36 
     37 #define N 1000005
     38 
     39 int n, m;
     40 int h[N];
     41 
     42 struct node
     43 {
     44     int lt, rt, cnt;
     45     long long sum;
     46 }tree[N * 6];
     47 
     48 void build(int p, int l, int r)
     49 {
     50     node &t = tree[p];
     51     
     52     t.lt = l;
     53     t.rt = r;
     54     
     55     t.cnt = t.sum = 0;
     56     
     57     if (l ^ r)
     58     {
     59         int mid = (l + r) >> 1;
     60         
     61         build(p << 1, l, mid);
     62         build(p << 1 | 1, mid + 1, r);
     63     }
     64 }
     65 
     66 void insert(int p, int pos, int val1, int val2)
     67 {
     68     node &t = tree[p];
     69     
     70     t.cnt += val1;
     71     t.sum += val2;
     72     
     73     if (t.lt ^ t.rt)
     74     {
     75         int mid = (t.lt + t.rt) >> 1;
     76         
     77         if (pos <= mid)
     78             insert(p << 1, pos, val1, val2);
     79         else
     80             insert(p << 1 | 1, pos, val1, val2);
     81     }
     82 }
     83 
     84 int query1(int p, int rank)
     85 {
     86     node &t = tree[p];
     87     
     88     if (t.lt == t.rt)return t.lt;
     89     
     90     if (tree[p << 1].cnt >= rank)
     91         return query1(p << 1, rank);
     92     else
     93         return query1(p << 1 | 1, rank - tree[p << 1].cnt);    
     94 }
     95 
     96 long long query2(int p, int l, int r)
     97 {
     98     if (l > r)return 0LL;
     99     
    100     node &t = tree[p];
    101     
    102     if (l == t.lt && r == t.rt)
    103         return t.sum;
    104         
    105     int mid = (t.lt + t.rt) >> 1;
    106     
    107     if (r <= mid)
    108         return query2(p << 1, l, r);
    109     if (l > mid)
    110         return query2(p << 1 | 1, l, r);
    111     return query2(p << 1, l, mid) + query2(p << 1 | 1, mid + 1, r);
    112 }
    113 
    114 int query3(int p, int l, int r)
    115 {
    116     if (l > r)return 0LL;
    117     
    118     node &t = tree[p];
    119     
    120     if (l == t.lt && r == t.rt)
    121         return t.cnt;
    122         
    123     int mid = (t.lt + t.rt) >> 1;
    124     
    125     if (r <= mid)
    126         return query3(p << 1, l, r);
    127     if (l > mid)
    128         return query3(p << 1 | 1, l, r);
    129     return query3(p << 1, l, mid) + query3(p << 1 | 1, mid + 1, r);
    130 }
    131 
    132 signed main(void)
    133 {
    134     fread(c, 1, lim, stdin);
    135     
    136     read(n); 
    137     read(m);
    138     
    139     ri maxi = 0;
    140     ri mini = N;
    141     
    142     for (ri i = 1; i <= n; ++i)
    143     {
    144         read(h[i]);
    145         
    146         Min(mini, h[i]);
    147         Max(maxi, h[i]);
    148     }
    149     
    150     build(1, 0, N);
    151     
    152     for (ri i = 1; i < m; ++i)
    153         insert(1, h[i], 1, h[i]);
    154         
    155     int d = (m + 1) >> 1;
    156     
    157     long long ans = 1e18 + 9;
    158         
    159     for (ri i = m; i <= n; ++i)
    160     {
    161         insert(1, h[i], 1, h[i]);
    162         
    163         {
    164             int mid = d;
    165             
    166             long long q = query1(1, mid), res = 0LL;
    167             
    168             long long lc = query3(1, 0, q - 1);
    169             long long rc = query3(1, q + 1, N);
    170             
    171             res += lc*q - query2(1, 0, q - 1);
    172             res += query2(1, q + 1, N) - rc*q;
    173             
    174             Min(ans, res);
    175         }
    176         
    177         insert(1, h[i - m + 1], -1, -h[i - m + 1]);
    178     }
    179     
    180     printf("%lld
    ", ans);
    181 }
    BZOJ_1112.cpp

    @Author: YouSiki

  • 相关阅读:
    查看Eclipse版本号的方法
    设置Eclipse的字体风格方式
    又遇两个小异常
    我所推崇的三种心态
    关于javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in &lt;forEach&gt;
    Http请求中Content-Type讲解
    ftp实现文件上传(下载)
    解析html文档的java库及范例
    xslt循环转换子元素
    XPath学习:轴(1)——child
  • 原文地址:https://www.cnblogs.com/yousiki/p/6091630.html
Copyright © 2020-2023  润新知