• bzoj 1112 [POI2008]砖块Klo


     [POI2008]砖块Klo

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2196  Solved: 787
    [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

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

     
    题解:水水的一道题目,划水就可以过了。
       因为区间k固定,所以每次绝对是取中位数的,
       那么只需要一个数据结构,支持寻找中位数,插入,删除,
       求和,这些即可。
       
       那就是Treap瞎搞即可。
      1 #include<cstring>
      2 #include<cmath>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<cstdio>
      6 
      7 #define ll long long
      8 #define ls tr[p].l
      9 #define rs tr[p].r
     10 #define N 100007
     11 using namespace std;
     12 const ll inf=2000000000000010;
     13 inline ll read()
     14 {
     15     ll x=0,f=1;char ch=getchar();
     16     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
     17     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
     18     return x*f;
     19 }
     20 
     21 ll n,sz,rt,ans,k;
     22 ll a[N];
     23 struct Node
     24 {
     25     ll l,r,val,siz,rnd,ct,sum;//记录左儿子,右儿子,点值,该子树大小,随机的值,该点值出现的次数。 
     26 }tr[N*10];//最多多少个节点,就开多少空间 
     27 
     28 inline int rand()
     29 {
     30     static ll seed = 2333;
     31     return seed = (ll)((((seed ^ 998244353) + 19260817ll) * 19890604ll) % 1000000007);
     32 }
     33 inline void update(ll p)
     34 {
     35     tr[p].siz=tr[ls].siz+tr[rs].siz+tr[p].ct;
     36     tr[p].sum=tr[ls].sum+tr[rs].sum+tr[p].ct*tr[p].val;
     37 }
     38 void lturn(ll &p)
     39 {
     40     ll t=tr[p].r;tr[p].r=tr[t].l;tr[t].l=p;
     41     update(t),update(p);p=t;
     42 }
     43 void rturn(ll &p)
     44 {
     45     ll t=tr[p].l;tr[p].l=tr[t].r;tr[t].r=p;
     46     tr[t].siz=tr[p].siz;update(p);p=t;
     47 }
     48 void ins(ll &p,ll x)
     49 {
     50     if (p==0)
     51     {
     52         p=++sz;
     53         tr[p].siz=tr[p].ct=1,tr[p].val=x,tr[p].sum=x,tr[p].rnd=rand();
     54         return;
     55     }
     56     tr[p].siz++;
     57     if (tr[p].val==x) tr[p].ct++;
     58     else if (x>tr[p].val)
     59     {
     60         ins(tr[p].r,x);
     61         if (tr[rs].rnd<tr[p].rnd) lturn(p);
     62     }else
     63     {
     64         ins(tr[p].l,x);
     65         if (tr[ls].rnd<tr[p].rnd) rturn(p);
     66     }
     67     update(p);
     68 }
     69 void del(ll &p,ll x)
     70 {
     71     if (p==0) return;
     72     if (tr[p].val==x)
     73     {
     74         if (tr[p].ct>1) tr[p].ct--,tr[p].siz--,tr[p].sum-=x;//如果有多个直接减一即可。
     75         else
     76         {
     77             if (ls==0||rs==0) p=ls+rs;//单节点或者空的话直接儿子移上来或者删去即可。
     78             else if (tr[ls].rnd<tr[rs].rnd) rturn(p),del(p,x);
     79             else lturn(p),del(p,x); 
     80         }
     81     }
     82     else if (x>tr[p].val) tr[p].siz--,del(rs,x),tr[p].sum-=x;
     83     else tr[p].siz--,del(ls,x),tr[p].sum-=x;
     84     update(p);
     85 }
     86 void solve(ll p,ll x,ll &sum,ll &num,ll &ge,ll &zhi)
     87 {
     88     if (tr[ls].siz>=x) solve(ls,x,sum,num,ge,zhi);
     89     else
     90     {
     91         x-=tr[ls].siz,sum+=tr[ls].sum,num+=tr[ls].siz;
     92         if (tr[p].ct>=x)
     93         {
     94             ge=tr[p].ct;
     95             zhi=tr[p].val;
     96             return;
     97         }
     98         x-=tr[p].ct,sum+=tr[p].val*tr[p].ct,num+=tr[p].ct;
     99         solve(rs,x,sum,num,ge,zhi);
    100     }
    101 }
    102 int main()
    103 {
    104     freopen("fzy.in","r",stdin);
    105     freopen("fzy.out","w",stdout);
    106     
    107     n=read(),k=read();
    108     for (ll i=1;i<=k;i++)
    109         a[i]=read(),ins(rt,a[i]);
    110 //    cout<<tr[rt].val<<endl;    
    111     ans=inf;
    112     for (ll i=k+1;i<=n+1;i++)
    113     {
    114         ll x=0,y=0,z=0,d=0;
    115         solve(rt,(k+1)/2,x,y,z,d);
    116         //cout<<x<<" "<<y<<" "<<z<<" "<<d<<endl;
    117         ll res=0;
    118         res+=d*y-x;
    119         res+=tr[rt].sum-x-z*d-d*(tr[rt].siz-y-z);
    120         ans=min(ans,res);
    121         if (i<=n)
    122         {
    123             del(rt,a[i-k]);
    124             a[i]=read();
    125             ins(rt,a[i]);
    126         }
    127     }
    128     printf("%lld",ans);
    129 }
  • 相关阅读:
    bzoj 1176 cdq分治套树状数组
    Codeforces 669E cdq分治
    Codeforces 1101D 点分治
    Codeforces 1100E 拓扑排序
    Codeforces 1188D Make Equal DP
    Codeforces 1188A 构造
    Codeforces 1188B 式子转化
    Codeforces 1188C DP 鸽巢原理
    Codeforces 1179D 树形DP 斜率优化
    git commit -m "XX"报错 pre -commit hook failed (add --no-verify to bypass)问题
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8065771.html
Copyright © 2020-2023  润新知