bzoj 1112: [POI2008]砖块Klo treap

来源:互联网 发布:excel 销售数据分析 编辑:程序博客网 时间:2024/04/18 15:20

题意

给出n个数,每次操作可以让一个数+1或-1,求连续的m个数,使得他们变成相同的数的操作数最少。
n,m<=100000

分析

假设现在给出m个数,要想使得他们变成相同的数的操作数最少,显然要让他们都变成这个m个数的中位数。
知道了这个后我们就可以用一棵treap来暴力这个m个值,然后每次查找中位数即可。

第一次用c++写treap,感觉好虚啊,顺便去借鉴了一波黄学长的删除操作。话说黄学长的代码真心简洁明了啊%%%

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 100005#define ll long longusing namespace std;int n,m,a[N],size,tot,root;ll sum,ans;struct tree{int size,val,in,l,r,k;ll s;}t[N];void updata(int x){    t[x].size=t[t[x].l].size+t[t[x].r].size+t[x].in;    t[x].s=t[t[x].l].s+t[t[x].r].s+(ll)t[x].in*t[x].val;}void rttl(int &x){    int y=t[x].r;    t[x].r=t[y].l;    t[y].l=x;    updata(x);    updata(y);    x=y;}void rttr(int &x){    int y=t[x].l;    t[x].l=t[y].r;    t[y].r=x;    updata(x);    updata(y);    x=y;}void ins(int &x,int val){    if (!x)    {        x=++tot;        t[x].val=t[x].s=val;t[x].size=t[x].in=1;t[x].k=rand();        return;    }    t[x].s+=val;t[x].size++;    if (t[x].val==val)    {        t[x].in++;        return;    }    if (val<t[x].val)    {        ins(t[x].l,val);        if (t[t[x].l].k<t[x].k) rttr(x);    }else    {        ins(t[x].r,val);        if (t[t[x].r].k<t[x].k) rttl(x);    }}void del(int &x,int val){    if (!x) return;    if (t[x].val==val)    {        if (t[x].in>1)        {            t[x].in--;t[x].size--;t[x].s-=val;return;        }        else if (t[x].l*t[x].r==0)        {            x=t[x].l+t[x].r;return;        }        else if (t[t[x].l].k<t[t[x].r].k)        {            rttr(x);del(t[x].r,val);        }        else        {            rttl(x);del(t[x].l,val);        }    }    else if (val<t[x].val) del(t[x].l,val);    else del(t[x].r,val);    updata(x);}int find(int x,int y){    if (t[t[x].l].size+1<=y&&t[t[x].l].size+t[x].in>=y)    {        sum+=t[t[x].l].s;size+=t[t[x].l].size;        return t[x].val;    }    if (t[t[x].l].size+t[x].in<y)    {        sum+=t[t[x].l].s+(ll)t[x].val*t[x].in;size+=t[t[x].l].size+t[x].in;        y-=t[t[x].l].size+t[x].in;        return find(t[x].r,y);    }else    {        return find(t[x].l,y);    }}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=n;i++)        scanf("%d",&a[i]);    t[0].k=1e7;    for (int i=1;i<=m;i++)        ins(root,a[i]);    ll ans=1e17;    sum=size=0;    int x=find(root,(1+m)/2);    ans=min(ans,(ll)x*size-sum+t[root].s-sum-(ll)x*(m-size));    for (int i=m+1;i<=n;i++)    {        del(root,a[i-m]);        ins(root,a[i]);        sum=size=0;        int x=find(root,(1+m)/2);        ans=min(ans,(ll)x*size-sum+t[root].s-sum-(ll)x*(m-size));    }    printf("%lld",ans);    return 0;}
0 0