[Bzoj1112][POI2008]砖块Klo(splay)
Posted lzdhydzzh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Bzoj1112][POI2008]砖块Klo(splay)相关的知识,希望对你有一定的参考价值。
1112: [POI2008]砖块Klo
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2353 Solved: 831
[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
原题还要求输出结束状态时,每柱砖的高度.本题略去.
分析:
splay求中位数。
AC代码:
# include <iostream> # include <cstdio> # include <cstring> using namespace std; typedef long long LL; const int N = 1e5 + 12; LL s[N],ret = 1e18;int n,K,root,cnt; struct node{ int ch[2]; int fa; int sz;LL val,sum; node(){} node(LL val):fa(0),sz(1),val(val),sum(sum){ch[0] = ch[1] = 0;} }a[N]; void push(int x) { a[x].sz = a[a[x].ch[0]].sz + a[a[x].ch[1]].sz + 1; a[x].sum = a[a[x].ch[0]].sum + a[a[x].ch[1]].sum + a[x].val; } void rotate(int now,int d) { int pre = a[now].fa,g = a[pre].fa,nex = a[now].ch[d]; a[pre].ch[d ^ 1] = nex; if(nex)a[nex].fa = pre; a[now].fa = g; if(g)a[g].ch[a[g].ch[1] == pre] = now; a[pre].fa = now;a[now].ch[d] = pre; push(pre);push(now); } void splay(int now) { int pre,g; while(a[now].fa) { pre = a[now].fa,g = a[pre].fa; if(g && !((a[pre].ch[0] == now) ^ (a[g].ch[0] == pre)))rotate(pre,a[pre].ch[0] == now); rotate(now,a[pre].ch[0] == now); } root = now; } void insert(LL val) { if(!root){a[++cnt] = node(val);root = cnt;return;} int now = root,pre; while(now) { pre = now; now = a[now].ch[val > a[now].val]; } a[++cnt] = node(val);a[cnt].fa = pre; a[pre].ch[val > a[pre].val] = cnt; splay(cnt); } void erase(int now) { splay(now); if(!a[now].ch[0] || !a[now].ch[1]){root = a[now].ch[0] + a[now].ch[1];} else { int p = a[now].ch[1]; while(a[p].ch[0])p = a[p].ch[0]; a[p].ch[0] = a[now].ch[0]; a[a[now].ch[0]].fa = p; root = a[now].ch[1];a[root].fa = 0; splay(a[now].ch[0]); } a[root].fa = 0; } int find(int k) { int now = root; while(k > 0) { if(a[a[now].ch[0]].sz < k){k -= a[a[now].ch[0]].sz;k--;if(k > 0)now = a[now].ch[1];} else now = a[now].ch[0]; } return now; } int main() { scanf("%d %d",&n,&K); for(int i = 1;i <= n;i++)scanf("%lld",&s[i]); for(int i = 1;i < K;i++)insert(s[i]); for(int i = K;i <= n;i++) { if(i - K)erase(i - K); insert(s[i]); int now = find((K + 1) >> 1); splay(now); LL s1 = a[a[now].ch[0]].sz,s2 = a[a[now].ch[1]].sz; LL pre = a[a[now].ch[0]].sum,bef = a[a[now].ch[1]].sum; if(s1 * a[now].val - pre + bef - s2 * a[now].val < ret)ret = s1 * a[now].val - pre + bef - s2 * a[now].val; } printf("%lld\n",ret); }
以上是关于[Bzoj1112][POI2008]砖块Klo(splay)的主要内容,如果未能解决你的问题,请参考以下文章