zoukankan      html  css  js  c++  java
  • Bzoj1112--Poi2008砖块Klo

    要使一个连续区间内的高度相同改变量最小,想想其实就是直线上很多点,选一个到所有点距离和最小的位置这种

    平衡树维护一发中位数即可

    对于花费是可以由上一个区间的花费计算过来的

    只用比较一下前一次中位数和这一次中位数谁大,然后各自加加减减。例如2 3 3 5 2 4 ,找长度为3的区间,假设我们找到了3 5 2的花费为3,中位数为3,要求5 2 4的花费就是先减去3的花费0,加上4的花费1,得到5 2 4全部变到3的花费为4,然后因为这一次的中位数是4,所以把大于等于4的数花费减1,小于等于3的数花费加1,得到花费为3。

    为了方便用了游程编码

    代码:

    #include<bits/stdc++.h>
    #define MAXN 100005
    #define MAXM 3005
    #define INF 10000000000000LL
    #define MOD 10000007
    #define LL long long
    #define int long long
    using namespace std;
    
    inline int read() {
        int ret=0,f=1;char c=getchar();
        while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
        while(c<='9'&&c>='0') {ret=ret*10+c-'0';c=getchar();}
        return ret*f;
    }
    
    int n,k,a[MAXN];
    
    struct node{
        int son[2],s,par,sz;LL v,r;
    }x[MAXN];
    struct Treap{
        int L,R,root,cnt;
        void init() {
            L=0;R=1;root=MAXN-5;cnt=0;
            x[MAXN-5].r=INF;x[MAXN-5].v=INF;
        }
        
        inline void rotate(int num,int p) {
            int pa=x[num].par,t=x[num].sz;
            x[x[pa].par].son[x[x[pa].par].son[L]==pa?L:R]=num;
            x[num].sz=x[pa].sz;x[pa].sz-=t-x[x[num].son[p]].sz;
            x[pa].son[p^1]=x[num].son[p];if(x[num].son[p]) {x[x[num].son[p]].par=pa;}
            x[num].son[p]=pa;x[num].par=x[pa].par;x[pa].par=num;
        }
        
        void Insert(int v) {
            x[++cnt].v=v;x[cnt].r=rand()%MOD+1;x[cnt].s=1;x[cnt].sz=1;
            int now=root,pre;
            while(true) {
                if(v==x[now].v) {x[now].s++;x[now].sz++;cnt--;return;}
                pre=v<x[now].v?L:R;x[now].sz++;
                if(!x[now].son[pre]) {x[now].son[pre]=cnt;x[cnt].par=now;break;}
                now=x[now].son[pre];
            }
            now=cnt;
            while(true) {
                if(x[x[now].par].son[L]==now) pre=R;else pre=L;
                if(x[now].r>x[x[now].par].r) rotate(now,pre);
                else break;
            }
        }
        inline void Updata(int num,int v) {
            num=x[num].par;
            while(num) x[num].sz+=v,num=x[num].par;
        }
        void Del(int v) {
            int now=root;
            while(true) {
                if(v==x[now].v) {
                    if(x[now].s>1) {x[now].s--;x[now].sz--;Updata(now,-1);return;}
                    break;
                }
                now=x[now].son[v<x[now].v?L:R];
            }
            while(x[now].son[L]|x[now].son[R])
                if(x[x[now].son[L]].r>x[x[now].son[R]].r) rotate(x[now].son[L],R);
                else rotate(x[now].son[R],L);
            Updata(now,-1);
            x[x[now].par].son[x[x[now].par].son[L]==now?L:R]=0;
        }
        int Qurey(int k) {
            int now=root;
            if(k>x[root].sz) return -1;
            while(true) {
                if(x[x[now].son[L]].sz>=k-x[now].s&&x[x[now].son[L]].sz<k) return x[now].v;
                if(x[x[now].son[L]].sz<k) {k-=x[now].s+x[x[now].son[L]].sz;now=x[now].son[R];}
                else now=x[now].son[L];
                
            }
        }
        int Count_Treap(int v,int num) {
            if(!num) return 0;
            if(x[num].v>v) return Count_Treap(v,x[num].son[L]);
            else return Count_Treap(v,x[num].son[R])+x[x[num].son[L]].sz+x[num].s;
        }
        int Count(int v) {return Count_Treap(v,root);}
    };
    
        #undef int
    int main() {
        #define int long long
        srand(233333);
        n=read();k=read();
        for(int i=1;i<=n;i++) a[i]=read();
        Treap p;p.init();
        for(int i=1;i<=k;i++) p.Insert(a[i]);
        LL cost=0,ans=0;
        LL t=p.Qurey(k+1>>1),lt,delta,deltat;
        for(int i=1;i<=k;i++) cost+=abs(a[i]-t);
        ans=cost;lt=t;
        for(int i=k+1;i<=n;i++) {
            p.Del(a[i-k]);p.Insert(a[i]);
            t=p.Qurey(k+1>>1);
            delta=p.Count(min(t,lt));deltat=abs(t-lt);
            cost-=abs(a[i-k]-lt)-abs(a[i]-lt);
            if(t>lt) cost+=delta*deltat-(k-delta)*deltat;
            else cost+=(k-delta)*deltat-delta*deltat;
            ans=min(ans,cost);lt=t;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    ●SPOJ 8222 NSUBSTR–Substrings(后缀自动机)
    ●SPOJ 1811 Longest Common Substring
    ●POJ 1509 Glass Beads
    ●BZOJ 4556 [Tjoi2016&Heoi2016]字符串
    ●BOZJ 2229 [Zjoi2011]最小割
    ●BOZJ 4456 [Zjoi2016]旅行者
    ●观光(17.12.02多校联测题目)
    ●BZOJ 2007 NOI 2010 海拔
    mysql--->B+tree索引的设计原理
    mysql--->权限管理原理和设置
  • 原文地址:https://www.cnblogs.com/ihopenot/p/5918563.html
Copyright © 2011-2022 走看看