• Luogu 3466 [POI2008]KLO-Building blocks


    BZOJ 1112。

    题意相当于在一个长度为$k$的区间内选择一个数$s$使$sum_{i = 1}^{k}left | a_i - s ight |$最小。

    很显然是中位数。

    然后只要写一个能查询长度为$k$的区间的中位数,以及小于和大于这个中位数的总和和个数的数据结构即可。

    线段树平衡树对顶堆随便维护。

    我选择权值线段树。

    时间复杂度$O(nlogn)$。

    Luogu上还需要输出方案。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N = 1e5 + 5;
    
    int n, K;
    ll mn = 0LL, a[N];
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op; 
    }
    
    template <typename T>
    inline void chkMax(T &x, T y) {
        if(y > x) x = y;
    }
    
    namespace SegT {
        struct Node {
            int lc, rc;
            ll sum, cnt;
        } s[N * 40];
    
        int root, nodeCnt = 0;
        
        #define lc(p) s[p].lc
        #define rc(p) s[p].rc
        #define sum(p) s[p].sum
        #define cnt(p) s[p].cnt
        #define mid ((l + r) >> 1)
    
        void ins(int &p, ll l, ll r, ll x) {
            if(!p) p = ++nodeCnt;
            sum(p) += x, ++cnt(p);
            if(l == r) return;
    
            if(x <= mid) ins(lc(p), l, mid, x);
            else ins(rc(p), mid + 1, r, x);
        }
    
        void del(int &p, ll l, ll r, ll x) {
            sum(p) -= x, --cnt(p);
            if(l == r) return;
    
            if(x <= mid) del(lc(p), l, mid, x);
            else del(rc(p), mid + 1, r, x);
        }
    
        ll getKth(int p, ll l, ll r, int k) {
            if(l == r) return l;
    
            int now = cnt(lc(p));
            if(k <= now) return getKth(lc(p), l, mid, k);
            else return getKth(rc(p), mid + 1, r, k - now);
        }
    
        int qCnt(int p, ll l, ll r, ll x, ll y) {
            if(x <= l && y >= r) return cnt(p);
    
            int res = 0;
            if(x <= mid) res += qCnt(lc(p), l, mid, x, y);
            if(y > mid) res += qCnt(rc(p), mid + 1, r, x, y);
            return res;
        }
    
        ll qSum(int p, ll l, ll r, ll x, ll y) {
            if(x <= l && y >= r) return sum(p);
    
            ll res = 0LL;
            if(x <= mid) res += qSum(lc(p), l, mid, x, y);
            if(y > mid) res += qSum(rc(p), mid + 1, r, x, y);
            return res;
        }
    
        #undef mid
    
    } using namespace SegT;
    
    int main() {
        read(n), read(K);
        for(int i = 1; i <= n; i++) {
            read(a[i]);
            chkMax(mn, a[i]);
        }
    
    //    ll sum = 0LL;
        for(int i = 1; i <= K; i++) {
    //        sum += a[i];
            ins(root, 0, mn, a[i]);
        }
    
        int pos = 1;
        ll mid = getKth(root, 0, mn, (K + 1) / 2); 
        ll minCost = mid * qCnt(root, 0, mn, 0, mid) - qSum(root, 0, mn, 0, mid);
        minCost += qSum(root, 0, mn, mid + 1, mn) - mid * qCnt(root, 0, mn, mid + 1, mn);
        for(int i = K + 1; i <= n; i++) {
            del(root, 0, mn, a[i - K]);
            ins(root, 0, mn, a[i]);
    
            ll nowMid = getKth(root, 0, mn, (K + 1) / 2); 
            ll nowCost = nowMid * qCnt(root, 0, mn, 0, nowMid) - qSum(root, 0, mn, 0, nowMid);
            nowCost += qSum(root, 0, mn, nowMid + 1, mn) - nowMid * qCnt(root, 0, mn, nowMid + 1, mn);
    
            if(nowCost < minCost) {
                pos = i - K + 1;
                mid = nowMid;
                minCost = nowCost;
            }
        }
    
        printf("%lld
    ", minCost);
    /*    for(int i = 1; i <= n; i++) {
            if(i >= pos && i <= pos + K - 1) printf("%lld
    ", mid);
            else printf("%lld
    ", a[i]);
        }   */
    
        return 0;
    }
    View Code
  • 相关阅读:
    命令行推送文章到博客园
    链表的新写法
    关于vim无法复制到剪切板的问题
    Ethernet & ARP Protocol
    [从今天开始修炼数据结构]串、KMP模式匹配算法
    [从今天开始修炼数据结构]队列、循环队列、PriorityQueue的原理及实现
    [从今天开始修炼数据结构]栈、斐波那契数列、逆波兰四则运算的实现
    [从今天开始修炼数据结构]线性表及其实现以及实现有Itertor的ArrayList和LinkedList
    IntelliJ IDEA快捷键大全
    [从今天开始修炼数据结构]基本概念
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9785527.html
Copyright © 2020-2023  润新知