bzoj 1112 treap

来源:互联网 发布:交互式动画制作软件 编辑:程序博客网 时间:2024/06/06 23:16

枚举每一个区间,用treap维护中位数和子树和更新答案
PS:treap代码风格一变再变,从指针(太难调试+太长了)->结构体(太长了)->数组

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=1e5+10;typedef long long ll;const ll linf=9223372036854775807LL;int l[N],r[N],s[N],w[N],rnd[N],K;ll v[N],sum[N],sum1,sum2,tmp,ans=linf,h[N];int n,m,size,root;void update(int k){    s[k]=s[l[k]]+s[r[k]]+w[k];    sum[k]=sum[l[k]]+sum[r[k]]+w[k]*v[k];}void rturn(int &k) {int t=l[k];l[k]=r[t];r[t]=k;update(k);update(t);k=t;}void lturn(int &k) {int t=r[k];r[k]=l[t];l[t]=k;update(k);update(t);k=t;}void insert(int &k,int val){    if(k==0) {k=++size;v[k]=sum[k]=val;rnd[k]=rand();s[k]=w[k]=1;return ;}    sum[k]+=val;s[k]++;    if(v[k]==val) w[k]++;    else if(val>v[k]){        insert(r[k],val);if(rnd[r[k]]<rnd[k])lturn(k);}    else {        insert(l[k],val);if(rnd[l[k]]<rnd[k])rturn(k);}}void del(int &k,int val){    if(k==0) return ;    if(v[k]==val) {        if(w[k]>1) {w[k]--;s[k]--;sum[k]-=val;return ;}        if(l[k]*r[k]==0) k=l[k]+r[k];        else if(rnd[r[k]]<rnd[l[k]])lturn(k),del(k,val);        else                        rturn(k),del(k,val);    }     else if(val>v[k]) {s[k]--;sum[k]-=val;del(r[k],val);}         else         {s[k]--;sum[k]-=val;del(l[k],val);}}void find(int k,int rk){    if(k==0) return ;    if(rk<=s[l[k]]) {        sum2+=(sum[r[k]]+v[k]*w[k]);        find(l[k],rk);    }else if(rk>s[l[k]]+w[k]) {        sum1+=(sum[l[k]]+v[k]*w[k]);        find(r[k],rk-s[l[k]]-w[k]);    }else {        sum1+=(sum[l[k]]+(rk-s[l[k]]-1)*v[k]);        sum2+=(sum[r[k]]+(s[l[k]]+w[k]-rk)*v[k]);        tmp=v[k];    }}void getans(){    sum1=sum2=0;    find(root,m);    ll sum=(m-1)*tmp-sum1+sum2-(K-m)*tmp;    if(sum<ans)ans=sum;}int main(){    scanf("%d%d",&n,&K);m=((K+1)>>1);    fo(i,1,n) scanf("%lld",&h[i]);    for(int i=1;i<=K;i++)        insert(root,h[i]);    getans();    for(int i=K+1;i<=n;i++)    {        del(root,h[i-K]);        insert(root,h[i]);        getans();    }    printf("%lld",ans);    return 0;}
原创粉丝点击