【BZOJ1112】砖块Klo

来源:互联网 发布:电脑优化软件知乎 编辑:程序博客网 时间:2024/05/17 08:39

题目链接:传送门
题解:
显然每次取中位数,暴力枚举区间,用一个平衡树维护就好啦

ps: splay插入时忘记旋转,T得飞起

//by sdfzchy#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define pa t[x].fa#define ls t[x].ch[0]#define rs t[x].ch[1]using namespace std;typedef long long LL;const int inf=(1<<30),N=100010,mod=1e9+7;int n,m,a[N],k;inline int in(){    char tmp=getchar();    int res=0,f=1;    while((tmp<'0'||tmp>'9')&&tmp!='-')tmp=getchar();    if(tmp=='-') f=-1,tmp=getchar();    while(tmp>='0'&&tmp<='9') res=(res<<1)+(res<<3)+(tmp^48),tmp=getchar();    return res*f;}int root;LL ans=inf;struct node{    int ch[2],siz,fa,cnt;    LL val,sum;}t[N];inline int gi(int x) {return t[pa].ch[1]==x;}inline void upd(int x){    t[x].siz=t[ls].siz+t[rs].siz+t[x].cnt;    t[x].sum=t[ls].sum+t[rs].sum+t[x].cnt*t[x].val;}void rot(int x){    int f=pa,g=t[pa].fa,o=gi(x);    if(g) t[g].ch[gi(f)]=x;t[x].fa=g;    t[f].ch[o]=t[x].ch[!o];t[t[x].ch[!o]].fa=f;    t[x].ch[!o]=f;t[f].fa=x;    upd(f),upd(x);}void splay(int x,int tar){    for(;pa!=tar;rot(x))        if(t[pa].fa!=tar)            rot((gi(x)==gi(pa))?pa:x);    if(!tar) root=x;}int cnt;void newnode(int &x,int val){    x=++cnt;    t[x].ch[0]=t[x].ch[1]=0;    t[x].siz=t[x].cnt=1;    t[x].val=t[x].sum=val;}void ins(int &x,int val,int fa){    if(!x) {newnode(x,val);pa=fa;splay(x,0);return;}    t[x].siz++;    if(t[x].val==val) {t[x].cnt++;t[x].sum+=val;return;}    if(val>t[x].val) ins(rs,val,x);    else ins(ls,val,x);    upd(x);}int find(int val){    int x=root;    while(x)    {        if(t[x].val==val) break;        if(val>t[x].val)  x=rs;        else x=ls;    }    if(x) splay(x,0);    return x;}void del(int val){    int x=find(val);    if(t[x].cnt>1) {t[x].cnt--;t[x].siz--;t[x].sum-=val;return;}    if(!ls&&!rs) root=0;    if(!ls) {root=rs;t[rs].fa=0;return;}    if(!rs) {root=ls;t[ls].fa=0;return;}    int pos=t[x].ch[0];    while(t[pos].ch[1]) pos=t[pos].ch[1];    splay(pos,x);    t[pos].ch[1]=rs;t[rs].fa=pos;t[pos].fa=0;root=pos;    upd(pos);}int kth(int kk){    int x=root;    while(x)    {        if(t[ls].siz>=kk) x=ls;        else if(t[ls].siz+t[x].cnt<kk) kk-=t[ls].siz+t[x].cnt,x=rs;        else return x;    }}void ga(){    int x=kth((k+1)>>1);    splay(x,0);    ans=min(ans,abs(t[x].val*t[ls].siz-t[ls].sum)+abs(t[x].val*t[rs].siz-t[rs].sum));}int main(){    ans=10000000000000000ll;    n=in(),k=in();    for(int i=1;i<=n;i++) a[i]=in();    for(int i=1;i<=k;i++) ins(root,a[i],0);    ga();    for(int i=k+1;i<=n;i++)    {        del(a[i-k]);        ins(root,a[i],0);        ga();    }    printf("%lld",ans);    return 0;}
原创粉丝点击