• [BZOJ1112] [POI2008] 砖块Klo (treap)


    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

    Solution

      妈丫BZOJ3224的$treap$调不出来只好另做一道$treap$简单题练手了。

      欸这道题还能用树状数组做么?本蒟蒻不会丫。

      这道题很容易想到,对于每一个区间,将区间内所有数改成该区间的中位数时开销最小。

      找中位数就是找第$(k+1)/2$的数$mid$嘛,于是一个$treap$的做法就诞生了。

      滑动窗口,每次保留$k$个数,求出比$mid$小的所有数的和$sum1$以及比$mid$大的所有数的和$sum2$

      答案就是$(sum1-(比mid小的数的个数)*mid)+((比mid大的数的个数)*mid-sum2)$

      欸好像可以化简,可以化简成$sum2-sum1$,$k$是偶数时多减一个$mid$

      普通$treap$,记一个$siz$和一个$sum$即可。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 struct treap
      5 {
      6     int l, r, siz, val, pri;
      7     ll key, sum;
      8 }a[100005];
      9 int root, ptot, h[100005];
     10 ll sum1, sum2;
     11  
     12 void push_up(int k)
     13 {
     14     a[k].siz = a[a[k].l].siz + a[a[k].r].siz + a[k].val;
     15     a[k].sum = a[a[k].l].sum + a[a[k].r].sum + a[k].key * a[k].val;
     16 }
     17  
     18 void lturn(int &k)
     19 {
     20     int tmp = a[k].r;
     21     a[k].r = a[tmp].l, a[tmp].l = k;
     22     a[tmp].siz = a[k].siz, a[tmp].sum = a[k].sum;
     23     push_up(k), k = tmp;
     24 }
     25  
     26 void rturn(int &k)
     27 {
     28     int tmp = a[k].l;
     29     a[k].l = a[tmp].r, a[tmp].r = k;
     30     a[tmp].siz = a[k].siz, a[tmp].sum = a[k].sum;
     31     push_up(k), k = tmp;
     32 }
     33  
     34 void insert(int &k, int x)
     35 {
     36     if(!k)
     37     {
     38         k = ++ptot, a[k].siz = a[k].val = 1;
     39         a[k].sum = a[k].key = x, a[k].pri = rand();
     40         return;
     41     }
     42     a[k].siz++, a[k].sum += x;
     43     if(x == a[k].key) a[k].val++;
     44     else if(x < a[k].key)
     45     {
     46         insert(a[k].l, x);
     47         if(a[k].pri < a[a[k].l].pri) rturn(k);
     48     }
     49     else
     50     {
     51         insert(a[k].r, x);
     52         if(a[k].pri < a[a[k].r].pri) lturn(k);
     53     }
     54 }
     55  
     56 void del(int &k, int x)
     57 {
     58     if(!k) return;
     59     if(x == a[k].key)
     60         if(a[k].val > 1) a[k].val--, a[k].siz--, a[k].sum -= x;
     61         else if(!(a[k].l * a[k].r)) k = a[k].l + a[k].r;
     62         else if(a[a[k].l].pri < a[a[k].r].pri) lturn(k), del(k, x);
     63         else rturn(k), del(k, x);
     64     else if(x < a[k].key) a[k].siz--, a[k].sum -= x, del(a[k].l, x);
     65     else a[k].siz--, a[k].sum -= x, del(a[k].r, x);
     66 }
     67  
     68 int query_num(int k, int x)
     69 {
     70     if(!k) return 0;
     71     if(x <= a[a[k].l].siz)
     72     {
     73         sum2 += a[a[k].r].sum + a[k].key * a[k].val;
     74         return query_num(a[k].l, x);
     75     }
     76     if(x <= a[a[k].l].siz + a[k].val)
     77     {
     78         sum1 += a[a[k].l].sum + (x - a[a[k].l].siz - 1) * a[k].key;
     79         sum2 += a[a[k].r].sum + (a[a[k].l].siz + a[k].val - x) * a[k].key;
     80         return a[k].key;
     81     }
     82     sum1 += a[a[k].l].sum + a[k].key * a[k].val;
     83     return query_num(a[k].r, x - a[a[k].l].siz - a[k].val);
     84 }
     85  
     86 int main()
     87 {
     88     int n, k, mid;
     89     ll ans = 100000000000000LL;
     90     cin >> n >> k, srand(n);
     91     for(int i = 1; i <= n; i++)
     92         cin >> h[i];
     93     for(int i = 1; i <= k; i++)
     94         insert(root, h[i]);
     95     for(int i = k + 1; i <= n + 1; i++)
     96     {
     97         sum1 = sum2 = 0;
     98         mid = query_num(root, (k + 1) >> 1);
     99         ans = min(ans, sum2 - sum1 - !(k & 1) * mid);
    100         insert(root, h[i]), del(root, h[i - k]);
    101     }
    102     cout << ans << endl;
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    QT,QVector 基本用法,遍历[实例讲解]
    QT boolinq
    Qt532.QString_填充字符
    QT AES加密
    允许ubuntu下mysql远程连接
    Curl参数一览
    PHP实现http与https转化
    LINUX查看硬件配置命令
    使用.htaccess的时候服务器出现500错误(在配置后台时出现)
    64位win7旗舰版搭建apache+php+mysql开发环境
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5449827.html
Copyright © 2020-2023  润新知