zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    Maven关于web.xml中Servlet和Servlet映射的问题
    intellij idea的Maven项目运行报程序包找不到的错误
    修改Maven项目默认JDK版本
    刷题15. 3Sum
    刷题11. Container With Most Water
    刷题10. Regular Expression Matching
    刷题5. Longest Palindromic Substring
    刷题4. Median of Two Sorted Arrays
    刷题3. Longest Substring Without Repeating Characters
    刷题2. Add Two Numbers
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5449827.html
Copyright © 2011-2022 走看看