zoukankan      html  css  js  c++  java
  • 【主席树】bzoj1112: [POI2008]砖块Klo

    数据结构划一下水

    Description

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

    Input

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

    Output

    最小的动作次数


    题目大意

    有一个非负的数列,可以±1修改高度,求最小代价使得连续k个高度相同

    题目分析

    对于一个区间的答案,就相当于把所有数都放在数轴上,再求一个数使得它到所有数的总和最小。那么最优就等于是求一个区间的中位数。

    于是问题相当于一个支持  求中位数;求比中位数小/大的数个数;求比中位数小/大的数总和  的数据结构。这个问题可以用主席树在$logn$内完成。

    注意 printf(calc(),a,b) ,如果在calc()中改变了a,b,输出的a,b将会是改变之前的值。

     1 #include<bits/stdc++.h>
     2 typedef long long ll;
     3 const int maxn = 100035;
     4 const int maxNode = 4000035;
     5 
     6 struct node
     7 {
     8     int val,l,r;
     9     ll sum;
    10 }a[maxNode];
    11 ll ans,lsum,rsum,lcnt,rcnt;
    12 int n,k;
    13 int rt[maxn],w[maxn],cnt[maxn],tot;
    14 
    15 int read()
    16 {
    17     char ch = getchar();
    18     int num = 0, fl = 1;
    19     for (; !isdigit(ch); ch=getchar())
    20         if (ch=='-') fl = -1;
    21     for (; isdigit(ch); ch=getchar())
    22         num = (num<<1)+(num<<3)+ch-48;
    23     return num*fl;
    24 }
    25 void build(int &rt, int l, int r)
    26 {
    27     rt = ++tot;
    28     if (l==r) return;
    29     int mid = (l+r)>>1;
    30     build(a[rt].l, l, mid);
    31     build(a[rt].r, mid+1, r);
    32 }
    33 void update(int pre, int &rt, int l, int r, int c)
    34 {
    35     rt = ++tot, a[rt] = a[pre], ++a[rt].val, a[rt].sum += cnt[c];
    36     if (l==r) return;
    37     int mid = (l+r)>>1;
    38     if (c <= mid) update(a[pre].l, a[rt].l, l, mid, c);
    39     else update(a[pre].r, a[rt].r, mid+1, r, c);
    40 }
    41 int query(int pre, int rt, int l, int r, int k)
    42 {
    43     if (l==r) return l;
    44     int val = a[a[rt].l].val-a[a[pre].l].val, mid = (l+r)>>1;
    45     if (val >= k){
    46         lcnt -= a[a[rt].r].val-a[a[pre].r].val;
    47         lsum -= a[a[rt].r].sum-a[a[pre].r].sum;
    48         return query(a[pre].l, a[rt].l, l, mid, k);
    49     }
    50     rcnt -= a[a[rt].l].val-a[a[pre].l].val;
    51     rsum -= a[a[rt].l].sum-a[a[pre].l].sum;
    52     return query(a[pre].r, a[rt].r, mid+1, r, k-val);
    53 }
    54 int main()
    55 {
    56     n = read(), k = read(), ans = 1ll<<60;
    57     for (int i=1; i<=n; i++) w[i] = cnt[i] = read();
    58     std::sort(cnt+1, cnt+n+1);
    59     cnt[0] = std::unique(cnt+1, cnt+n+1)-cnt-1;
    60     build(rt[0], 1, cnt[0]);
    61     for (int i=1; i<=n; i++)
    62     {
    63         w[i] = std::lower_bound(cnt+1, cnt+cnt[0]+1, w[i])-cnt;
    64         update(rt[i-1], rt[i], 1, cnt[0], w[i]);
    65     }
    66     for (int r=k; r<=n; r++)
    67     {
    68         int l = r-k;
    69         lcnt = rcnt = a[rt[r]].val-a[rt[l]].val, lsum = rsum = a[rt[r]].sum-a[rt[l]].sum;
    70         int tmp = cnt[query(rt[l], rt[r], 1, cnt[0], (k+1)>>1)];
    71         ans = std::min(ans, 1ll*tmp*(lcnt-rcnt)-lsum+rsum);
    72     }
    73     printf("%lld
    ",ans);
    74     return 0;
    75 }

    END

  • 相关阅读:
    Django项目:CMDB(服务器硬件资产自动采集系统)--01--01CMDB获取服务器基本信息
    rabbitmq 实现多个消费队列
    mssql附加的数据库查询的时候没有搜索权限
    mvc 返回json格式时间格式化
    HighChat动态绑定数据 数据后台绑定(四)
    双向绑定
    v-bind 属性绑定
    v-on 事件触发
    v-text和v-html绑定数据显示
    插值表达式
  • 原文地址:https://www.cnblogs.com/antiquality/p/10250745.html
Copyright © 2011-2022 走看看