• splay


    第一次ac的splay纪念(a题量跻身本校前十祭!!!)

    代码解决的是求中位数的问题具体见poi2008 block

    #include<bits/stdc++.h>
    #define M 1000000
    using namespace std;
    int size[M],ch[M][2],cnt[M],sum[M],f[M],key[M],sz,root;
    int h[M];
    void clear(int x){size[x]=ch[x][0]=ch[x][1]=cnt[x]=f[x]=key[x]=key[x]=0;}
    int get(int x){return ch[f[x]][1]==x;}
    void update(int x){
        if(x){
            size[x]=cnt[x];sum[x]=cnt[x]*key[x];
            if(ch[x][0]) size[x]+=size[ch[x][0]],sum[x]+=sum[ch[x][0]];
            if(ch[x][1]) size[x]+=size[ch[x][1]],sum[x]+=sum[ch[x][1]];
        }
    }
    void rotate(int x){
        int fa=f[x],gf=f[fa],which=get(x);
        ch[fa][which]=ch[x][which^1];f[ch[fa][which]]=fa;
        f[fa]=x;ch[x][which^1]=fa;
        f[x]=gf;
        if(gf) ch[gf][ch[gf][1]==fa]=x;
        update(fa),update(x);
    }
    void splay(int x){
        for(int fa;fa=f[x];rotate(x))
        if(f[fa]) rotate(get(x)==get(fa)?fa:x);
        root=x;
    }
    void insert(int v){
        if(root==0){sz++;ch[sz][0]=ch[sz][1]=f[sz]=0;key[sz]=v;size[sz]=cnt[sz]=1;sum[sz]=v;root=sz;return;}
        int now=root,fa=0;
        while(1){
            if(key[now]==v){
                cnt[now]++;update(now);update(fa);splay(now);break;
            }
            fa=now;
            now=ch[now][key[now]<v];
            if(now==0){
                sz++;
                ch[sz][0]=ch[sz][1]=0;
                key[sz]=v;
                size[sz]=1;cnt[sz]=1;
                f[sz]=fa;ch[fa][key[fa]<v]=sz;
                update(fa);
                splay(sz);
                break;
            }
        }
    }
    int find(int v){
        int ans=0,now=root;
        while(1){
            if(v<key[now]) now=ch[now][0];
            else{
                ans+=ch[now][0]?size[ch[now][0]]:0;
                if(v==key[now]){splay(now);return ans+1;}
                ans+=cnt[now];
                now=ch[now][1];
            }
        }
    }
    int findx(int x){
        int now=root;
        while(1){
            if(ch[now][0]&&x<=size[ch[now][0]])
            now=ch[now][0];
            else{
                int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
                if(x<=temp) return now;
                x-=temp;now=ch[now][1];
            }
        }
    }
    int pre(){
        int now=ch[root][0];
        while(ch[now][1])now=ch[now][1];
        return now;
    }
    int next(){
        int now=ch[root][1];
        while(ch[now][0]) now=ch[now][0];
        return now;
    }
    void del(int x){
        int whatever=find(x);
        if(cnt[root]>1){cnt[root]--;return;}
        if(!ch[root][0]&&!ch[root][1]){clear(root);root=0;return;}
        if(!ch[root][0]){
            int oldroot=root;root=ch[root][1];f[root]=0;clear(oldroot);return;
        }
        else if(!ch[root][1]){
            int oldroot=root;root=ch[root][0];f[root]=0;clear(oldroot);return;
        }
        int leftbig=pre(),oldroot=root;
        splay(leftbig);
        f[ch[oldroot][1]]=root;
        ch[root][1]=ch[oldroot][1];
        clear(oldroot);
        update(root);
        return;
    }
    int main(){
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
        scanf("%d",&h[i]);
        for(int i=1;i<=k;i++)
        insert(h[i]);
        int p=(k+1)/2;
        int tmp=findx(p);
        splay(tmp);
        long long ans=size[ch[tmp][0]]*key[tmp]-sum[ch[tmp][0]]+sum[ch[tmp][1]]-key[tmp]*size[ch[tmp][1]];
        for(int i=2;i<=n-k+1;i++){
            del(h[i-1]);insert(h[i+k-1]);
            tmp=findx(p);
            splay(tmp);
            ans=min((long long)size[ch[tmp][0]]*key[tmp]-sum[ch[tmp][0]]+sum[ch[tmp][1]]-key[tmp]*size[ch[tmp][1]],ans);
        }
        printf("%lld",ans);
    }
    哈哈哈

    月光抽出3个月祭

  • 相关阅读:
    nginx日志
    silverlight 双击事件
    Silverlight button 图片切换样式
    Caliburn.Micro学习笔记(一)----引导类和命名匹配规则
    关闭Outlook时最小化 dll
    wpf键盘记录器
    WPF之TreeList的实现方法(一)
    精典算法之详解 河内之塔
    精典算法之二分查找法
    指针数组和数组指针
  • 原文地址:https://www.cnblogs.com/mzh2017/p/8964203.html
Copyright © 2020-2023  润新知