BZOJ 1112: [POI2008]砖块Klo treap

来源:互联网 发布:刚注册的域名怎么使用 编辑:程序博客网 时间:2024/04/24 22:34

1112: [POI2008]砖块Klo

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

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


看完题想二分高度,想想不行,又想三分,又不行。。。GG去看题解

平衡树

线性枚举区间,用中位数作为最终状态,之后就可以用平衡树解决了


GG好多发,觉得数据有问题,看solve函数,绝壁不对,然后过了。。。

(当然,在改成现在这个鬼畜的东西之前,它应该是无比正确的)

#include<cmath>#include<ctime>#include<cstdio>#include<cstring>#include<cstdlib>#include<complex>#include<iostream>#include<algorithm>#include<iomanip>#include<vector>#include<string>#include<bitset>#include<queue>#include<map>#include<set>using namespace std;typedef long long ll;inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x*f;}inline void print(ll x){if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar('0'+x%10);}const int N=100100;int root,sz;ll h[N];struct treap{int ls,rs,w,rnd,val,sz;ll sum;}tr[N];inline void lturn(int &k){int t=tr[k].rs;tr[k].rs=tr[t].ls;tr[t].ls=k;tr[t].sz=tr[k].sz;tr[t].sum=tr[k].sum;tr[k].sz=tr[tr[k].ls].sz+tr[tr[k].rs].sz+tr[k].w;tr[k].sum=tr[tr[k].ls].sum+tr[tr[k].rs].sum+tr[k].val*tr[k].w;k=t;}inline void rturn(int &k){int t=tr[k].ls;tr[k].ls=tr[t].rs;tr[t].rs=k;tr[t].sz=tr[k].sz;tr[t].sum=tr[k].sum;tr[k].sz=tr[tr[k].ls].sz+tr[tr[k].rs].sz+tr[k].w;tr[k].sum=tr[tr[k].ls].sum+tr[tr[k].rs].sum+tr[k].val*tr[k].w;k=t;}void insert(int &k,int val){if(!k){k=++sz;tr[k].sz=tr[k].w=1;tr[k].sum=tr[k].val=val;tr[k].rnd=rand();return ;}tr[k].sz++;tr[k].sum+=val;if(tr[k].val==val){tr[k].w++;return ;}else if(val<tr[k].val){insert(tr[k].ls,val);if(tr[tr[k].ls].rnd<tr[k].rnd)rturn(k);}else {insert(tr[k].rs,val);if(tr[tr[k].rs].rnd<tr[k].rnd)lturn(k);}}void del(int &k,int val){if(!k)return ;if(tr[k].val==val){if(tr[k].w>1){tr[k].w--;tr[k].sz--;tr[k].sum-=val;return ;}if(0==tr[k].ls*tr[k].rs){k=tr[k].ls+tr[k].rs;return ;}if(tr[tr[k].ls].rnd<tr[tr[k].rs].rnd){rturn(k);del(k,val);return ;}lturn(k);del(k,val);return ;}tr[k].sz--;tr[k].sum-=val;val<tr[k].val?del(tr[k].ls,val):del(tr[k].rs,val);}int query_mid(int k,int rk){if(!k)return 0;if(tr[tr[k].ls].sz>=rk)return query_mid(tr[k].ls,rk);if(tr[tr[k].ls].sz+tr[k].w<rk)return query_mid(tr[k].rs,rk-tr[k].w-tr[tr[k].ls].sz);return tr[k].val;}ll query_presum(int k,int val){if(!k)return 0;if(tr[k].val<val)return tr[tr[k].ls].sum+1ll*tr[k].val*tr[k].w+query_presum(tr[k].rs,val);return query_presum(tr[k].ls,val);}ll query_subsum(int k,int val){if(!k)return 0;if(tr[k].val>val)return tr[tr[k].rs].sum+1ll*tr[k].val*tr[k].w+query_subsum(tr[k].ls,val);return query_subsum(tr[k].rs,val);}int query_presz(int k,int val){if(!k)return 0;if(tr[k].val<val)return tr[tr[k].ls].sz+tr[k].w+query_presz(tr[k].rs,val);return query_presz(tr[k].ls,val);}int query_subsz(int k,int val){if(!k)return 0;if(tr[k].val>val)return tr[tr[k].rs].sz+tr[k].w+query_subsz(tr[k].ls,val);return query_subsz(tr[k].rs,val);}int n,m;ll ans=0X3f3f3f3f3f3f3f3fll;inline void solve(){ll tmp=query_mid(root,(m>>1)+1),now;now=1ll*tmp*query_presz(root,tmp)-query_presum(root,tmp);now+=query_subsum(root,tmp)-1ll*query_subsz(root,tmp)*tmp;ans=min(ans,now);}int main(){n=read(),m=read();register int i;for(i=1;i<m;++i){h[i]=read();insert(root,h[i]);}for(i=m;i<=n;++i){h[i]=read();insert(root,h[i]);solve();del(root,h[i-m+1]);}print(ans);puts("");return 0;}/*5 3392312*/