【BZOJ】1112 [POI2008]砖块Klo 平衡树

来源:互联网 发布:淘宝逛网 编辑:程序博客网 时间:2024/04/20 10:44

题目传送门

今天一晚上就做了一道题,好颓废啊……

这题其实还挺水的,只不过本蒟蒻一直都不太想的进去,所以一直WA,一直懵逼。

其实这题的题意是在n个数中连续取k个,把这k个数都改成一个相同的数m,使得Σabs(a[i]-m)最小。

很显然,当m为当前k个数的中位数时,当前k个数的改动最小。至于为什么,我也不知道……

然后我们就可以把这题转化为一个滑动窗口的题目,总共有n-k+1个窗口,求当前窗口的改动最小值。

因为是滑动窗口,需要加点、删点,还要取中位数和求和,我们不难想到平衡树。

除了求和那一段我卡了一会,其他的都挺水的。

注意:加点和删点时记得注意对节点所在子树权值和的修改。主要是我也不知道为什么我忘了这一点了,然后就一直WA……

orz hzwer,最后还是看他的代码改的程序,最后AC,不愧是一代神犇

附上AC代码:

#include <cstdio>#include <cstdlib>#include <cctype>#include <algorithm>#define N 100010using namespace std;struct tree{long long sum,w,g,rnd,size;}t[N];int son[N][2],rt;long long n,m,a[N],ans,size,now,tmp,sum1,sum2,mid;inline char nc(){static char ch[100010],*p1=ch,*p2=ch;return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;}inline void read(long long &a){static char c=nc();long long f=1;for (;!isdigit(c);c=nc()) if (c=='-') f=-1;for (a=0;isdigit(c);a=a*10+c-'0',c=nc());a*=f;return;}inline void updata(int k){t[k].size=t[son[k][0]].size+t[son[k][1]].size+t[k].g;t[k].sum=t[son[k][0]].sum+t[son[k][1]].sum+t[k].w*t[k].g;return;}inline void turn(int &k,long long x){int p=son[k][x];son[k][x]=son[p][x^1];son[p][x^1]=k;updata(k),updata(p),k=p;return;}inline void ist(int &k,long long x){if (k==0){k=++size;t[k].w=x,t[k].rnd=rand();t[k].g=t[k].size=1,t[k].sum=x;return;}++t[k].size,t[k].sum+=x;if (t[k].w==x) ++t[k].g;else if (t[k].w<x){ist(son[k][1],x);if (t[son[k][1]].rnd<t[k].rnd) turn(k,1);}else {ist(son[k][0],x);if (t[son[k][0]].rnd<t[k].rnd) turn(k,0);}return;}inline void del(int &k,long long x){if (!k) return;if (t[k].w==x){if (t[k].g>1){--t[k].g,--t[k].size,t[k].sum-=x;return;}if (son[k][0]*son[k][1]==0) k=son[k][0]+son[k][1];else if (t[son[k][0]].rnd<t[son[k][1]].rnd) turn(k,0),del(k,x);else turn(k,1),del(k,x);}else {--t[k].size;if (t[k].w<x) t[k].sum-=x,del(son[k][1],x);else t[k].sum-=x,del(son[k][0],x);}return;}inline void find(int k,long long x){if (!k) return;if (x>t[son[k][0]].size&&x<=t[son[k][0]].size+t[k].g){sum1+=t[son[k][0]].sum+(x-t[son[k][0]].size-1)*t[k].w;sum2+=t[son[k][1]].sum+(t[son[k][0]].size+t[k].g-x)*t[k].w;mid=t[k].w;}else if (x<=t[son[k][0]].size){sum2+=t[k].g*t[k].w+t[son[k][1]].sum;find(son[k][0],x);}else {sum1+=t[k].g*t[k].w+t[son[k][0]].sum;find(son[k][1],x-t[son[k][0]].size-t[k].g);}return;}inline void work(){sum1=sum2=0;long long k=(m+1)>>1;find(rt,k);ans=min(ans,mid*(k-1)-sum1+sum2-mid*(m-k));return;}int main(void){read(n),read(m);for (int i=1; i<=n; ++i) read(a[i]);int j=1;ans=0x7fffffffffffffff;for (int i=1; i<=m; ++i) ist(rt,a[i]);work();for (int i=m+1; i<=n; ++i) del(rt,a[i-m]),ist(rt,a[i]),work();printf("%lld",ans);return 0;}


原创粉丝点击