bzoj 1112 treap

枚舉每一個區間,用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;
}
發佈了146 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章