• bzoj 1112 treap树


    思路:我们只要check一遍每个长度为k的区间就好啦,对于一个区间来说的最优值显然是中位数,我们显然要动态求

    第k大,所以需要一个二叉搜索树,用treap就好啦。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define pii pair<int,int>
    #define piii pair<int, pair<int,int> >
    
    using namespace std;
    
    const int N = 2e5 + 10;
    const int M = 10 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-6;
    
    int n, k, a[N];
    
    struct node {
        node* ch[2];
        int key, fix, sz, cnt;
        LL sum;
    
        void update() {
            sz = ch[0]->sz + ch[1]->sz + cnt;
            sum = ch[0]->sum + ch[1]->sum + 1ll * cnt * key;
        }
    };
    
    typedef node* P_node;
    
    struct Treap {
    
        node base[N], nil;
        P_node root, null, len;
    
        Treap() {
    
            root = null = &nil;
            null->key = null->fix = 1e9;
            null->sz = null->cnt = null->sum = 0;
            null->ch[0] = null->ch[1] = null;
            len = base;
        }
    
        P_node newnode(int tkey) {
            len->key = tkey;
            len->fix = rand();
            len->ch[0] = len->ch[1] = null;
            len->sz = len->cnt = 1;
            len->sum = tkey;
            return len++;
        }
    
        void rot(P_node &p, int d) {
            P_node k = p->ch[d ^ 1];
            p->ch[d ^ 1] = k->ch[d];
            k->ch[d] = p;
            p->update();
            k->update();
            p = k;
        }
    
        void _Insert(P_node &p, int tkey) {
            if(p == null) {
                p = newnode(tkey);
            } else if(p->key == tkey) {
                p->cnt++;
            } else {
                int d = tkey > p->key;
                _Insert(p->ch[d], tkey);
                if(p->ch[d]->fix > p->fix) {
                    rot(p, d ^ 1);
                }
            }
            p->update();
        }
    
        void _Delete(P_node &p, int tkey) {
            if(p == null) return;
            if(p->key == tkey) {
                if(p->cnt > 1) p->cnt--;
                else if(p->ch[0] == null) p = p->ch[1];
                else if(p->ch[1] == null) p = p->ch[0];
                else {
                    int d = p->ch[0]->fix > p->ch[1]->fix;
                    rot(p, d);
                    _Delete(p->ch[d], tkey);
                }
            } else {
                _Delete(p->ch[tkey > p->key], tkey);
            }
            p->update();
        }
    
        int _Kth(P_node p, int k) {
            if(p == null || k < 1 || k > p->sz) return 0;
            if(k < p->ch[0]->sz + 1) return _Kth(p->ch[0], k);
            if(k > p->ch[0]->sz + p->cnt) return _Kth(p->ch[1], k - p->ch[0]->sz - p->cnt);
            return p->key;
        }
    
        int _Rank(P_node p, int tkey, int res) {
            if(p == null) return -1;
            if(p->key == tkey) return p->ch[0]->sz + res + 1;
            if(tkey < p->key) return _Rank(p->ch[0], tkey, res);
            return _Rank(p->ch[1], tkey, res + p->ch[0]->sz + p->cnt);
        }
    
        int _Pred(P_node p, int tkey){
            if(p == null) return -1e9;
            if(tkey <= p->key) return _Pred(p->ch[0], tkey);
            return max(p->key, _Pred(p->ch[1], tkey));
        }
    
        int _Succ(P_node p, int tkey){
            if(p == null) return 1e9;
            if(tkey >= p->key) return _Succ(p->ch[1], tkey);
            return min(p->key, _Succ(p->ch[0], tkey));
        }
    
        void _Print(P_node p){
            if(p == null) return;
            _Print(p -> ch[0]);
            for(int i = 1; i <= p->cnt; i++) printf("%d ",p->key);
            _Print(p->ch[1]);
        }
    
        LL _Query(P_node p, int tkey) {
            if(p == null) return 0;
    
            if(p->key == tkey) {
                return 1ll * tkey * p->ch[0]->sz - p->ch[0]->sum + p->ch[1]->sum - 1ll * tkey * p->ch[1]->sz;
            } else if(p->key < tkey) {
                return 1ll * tkey * (p->ch[0]->sz + p->cnt) - (p->ch[0]->sum + 1ll * p->cnt * p->key) + _Query(p->ch[1], tkey);
            } else {
                return (p->ch[1]->sum + 1ll * p->cnt * p->key) - 1ll * tkey * (p->ch[1]->sz + p->cnt) + _Query(p->ch[0], tkey);
            }
        }
    
        void Insert(int tkey){ _Insert(root,tkey); }
        void Delete(int tkey){ _Delete(root,tkey); }
        int Kth(int k){ return _Kth(root,k); }
        int Rank(int tkey){ return _Rank(root,tkey,0); }
        int Pred(int tkey){ return _Pred(root,tkey); }
        int Succ(int tkey){ return _Succ(root,tkey); }
        void Print(){ _Print(root); printf("
    "); }
        LL Query(int tkey) { return _Query(root, tkey); }
    }tp;
    
    
    int main() {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
    
        for(int i = 1; i <= k; i++) {
            tp.Insert(a[i]);
        }
    
        int l = 1, r = k, mid = k / 2;
        if(k & 1) mid++;
    
        LL ans = INF;
    
        while(r <= n) {
            int num = tp.Kth(mid);
            ans = min(ans, tp.Query(num));
    
            tp.Delete(a[l++]);
            tp.Insert(a[++r]);
        }
        printf("%lld
    ", ans);
        return 0;
    }
    /*
    5 5
    3 9 2 3 1
    */
  • 相关阅读:
    P1509 找啊找啊找GF
    P1508 Likecloud-吃、吃、吃
    P1493 分梨子
    P1507 NASA的食物计划
    Java简单从文件读取和输出
    服务器和普通用户电脑的区别
    readUTF()和writeUTF()
    js中substring和substr的用法
    AfxMessageBox和MessageBox差别
    POJ 3691 &amp; HDU 2457 DNA repair (AC自己主动机,DP)
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9178438.html
Copyright © 2020-2023  润新知