zoukankan      html  css  js  c++  java
  • BZOJ 1112: [POI2008]砖块Klo1112( BST )

    枚举每个长度为k的区间, 然后用平衡树找中位数进行判断, 时间复杂度O(nlogn).

     早上起来精神状态不太好...连平衡树都不太会写了...果断去看了会儿番然后就A了哈哈哈

    --------------------------------------------------------------------------

    #include<bits/stdc++.h>
      
    #define rep(i, n) for(int i = 0; i < n; i++)
    #define clr(x, c) memset(x, c, sizeof(x))
     
    using namespace std;
     
    typedef long long ll;
     
    const int maxn = 100009;
    const int inf = 10000000;
     
    int n, k;
     
    struct Node {
    Node *ch[2], *p;
    int s, v;
    ll sum;
    inline void setc(Node* t, int d) {
    ch[d] = t;
    t->p = this;
    }
    inline bool d() {
    return this == p->ch[1];
    }
    inline void upd() {
    s = ch[0]->s + ch[1]->s + 1;
    sum = ch[0]->sum + ch[1]->sum + v;
    }
    } pool[maxn], *pt = pool, *root, *null;
     
    Node* newNode(int v) {
    pt->p = pt->ch[0] = pt->ch[1] = null;
    pt->s = 1;
    pt->v = pt->sum = v;
    return pt++;
    }
     
    void init() {
    null = pt++;
    null->s = null->sum = null->v = 0;
    null->ch[0] = null->ch[1] = null->p = null;
    root = newNode(inf);
    root->setc(newNode(-inf), 0);
    root->upd();
    }
     
    void rot(Node* t) {
    Node* p = t->p;
    int d = t->d();
    p->p->setc(t, p->d());
    p->setc(t->ch[d ^ 1], d);
    t->setc(p, d ^ 1);
    p->upd();
    if(root == p) root = t;
    }
     
    void splay(Node* t, Node* f = null) {
    while(t->p != f) {
    if(t->p->p != f)
       t->d() != t->p->d() ? rot(t) : rot(t->p);
    rot(t);
    }
    t->upd();
    }
     
    Node* select(int k) {
    for(Node* t = root; ;) {
    int s = t->ch[0]->s;
    if(k == s) return t;
    if(k > s)
       t = t->ch[1], k -= s + 1;
    else
       t = t->ch[0];
    }
    }
     
    int rank(int v) {
    int ans = 0;
    for(Node* t = root; t != null;) {
    if(t->v < v) 
       ans += t->ch[0]->s + 1, t = t->ch[1];
    else
       t = t->ch[0];
    }
    return ans;
    }
     
    void insert(int v) {
    int r = rank(v);
    Node *L = select(r - 1), *R = select(r);
    splay(L), splay(R, L);
    R->setc(newNode(v), 0);
    R->upd(), L->upd();
    }
     
    void del(int v) {
    int r = rank(v);
    Node *L = select(r - 1), *R = select(r + 1);
    splay(L), splay(R, L);
    R->setc(null, 0);
    R->upd(), L->upd();
    }
     
    ll work() {
    Node *L = select(0), *R = select(k + 1), *t = select((k >> 1) + 1);
    splay(L), splay(R, L);
    splay(t, R);
    return t->v * (t->ch[0]->s - t->ch[1]->s) + t->ch[1]->sum - t->ch[0]->sum;
    }
     
    int A[maxn];
     
    int main() {
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
    init();
    ll ans;
    cin >> n >> k;
    rep(i, n) {
       scanf("%d", A + i);
       if(i < k) insert(A[i]);
    }
    ans = work();
    for(int i = k; i < n; i++) {
    insert(A[i]);
    del(A[i - k]);
    ans = min(ans, work());
    }
    cout << ans << " ";
    return 0;
    }

    --------------------------------------------------------------------------

    1112: [POI2008]砖块Klo

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1288  Solved: 444
    [Submit][Status][Discuss]

    Description

    N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.

    Input

    第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000

    Output

    最小的动作次数

    Sample Input

    5 3
    3
    9
    2
    3
    1

    Sample Output

    2

    HINT

    原题还要求输出结束状态时,每柱砖的高度.本题略去.

    Source

  • 相关阅读:
    Go语言基础介绍
    webpack教程——css的加载
    Git忽略规则.gitignore梳理
    vue2.0路由-适合刚接触新手简单理解
    JAVA实现DES加密实现详解
    计算机网络: IP地址,子网掩码,网段表示法,默认网关,DNS服务器详解
    Storm:最火的流式处理框架
    神片和神回复
    论C#未来发展
    弄清UTF8和Unicode
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4670116.html
Copyright © 2011-2022 走看看