zoukankan      html  css  js  c++  java
  • NOIP2016 蚯蚓

    首先一个暴力的想法就是直接开一个堆来维护每一条蚯蚓,然后记录一下总体增加的长度即可。

    但是这样的复杂度是 (O(m log m)) 的,不足以通过本题。

    但是基于观察可以发现:

    • 对于两条在 (t, t + 1) 时刻被砍的蚯蚓 (i, j),在 (t + 2) 时刻及以后 (i) 被砍的两部分会比 (j) 相应的被砍的两部分长。

    证明如下:

    只需证 (lfloor p(a_i + qt) floor + q ge lfloor p(a_j + q(t + 1)) floor)

    可知 (lfloor p(a_j + q(t + 1)) floor = lfloor p(a_j + qt) + pq floor le lfloor p(a_j + qt) + q floor = lfloor p(a_j + qt) floor + q)

    显然有 (lfloor p(a_i + qt) floor ge lfloor p(a_j + qt) floor + q) 得证。

    对于另一部分使用类似证明即可。

    因此,每次被砍断后蚯蚓的两部分的长度都是单调递减的,那么对于这些蚯蚓咱们就不需要排序了。

    那么我们只需要按照蚯蚓被砍的顺序将这些蚯蚓加入一个数组即可。

    于此同时,我们需要取出当前长度最长的蚯蚓,所以还需要比较当前三个数组开头哪个元素最大。

    因此,需要使用队列来维护砍断后蚯蚓的两个部分,复杂度 (O(n log n + m))

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i, l, r) for (int i = l; i <= r; ++i)
    const int N = 1e5 + 5;
    const int inf = -1e9;
    struct node { int t, w;} ;
    int n, m, q, u, v, t, P = 1, a[N];
    queue <node> Q1, Q2;
    int read() {
        char c; int x = 0, f = 1;
        c = getchar();
        while (c > '9' || c < '0') { if(c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    bool cmp(int a, int b) { return a > b;}
    int solve (int x) {
        int tmp;
        if(Q1.empty() && Q2.empty()) tmp = q * x + a[P], ++P;
        else if(Q2.empty()) {
            if(P > n) tmp = (x - Q1.front().t) * q + Q1.front().w, Q1.pop();
            else {
                int A = q * x + a[P], B = (x - Q1.front().t) * q + Q1.front().w;
                if(A > B) tmp = A, ++P;
                else tmp = B, Q1.pop();
            }
        }
        else if(Q1.empty()) {
            if(P > n) tmp = (x - Q2.front().t) * q + Q2.front().w, Q2.pop();
            else {
                int A = q * x + a[P], B = (x - Q2.front().t) * q + Q2.front().w;
                if(A > B) tmp = A, ++P;
                else tmp = B, Q2.pop();
            }
        }
        else {
            if(P > n) {
                int A = (x - Q1.front().t) * q + Q1.front().w, B = (x - Q2.front().t) * q + Q2.front().w;
                if(A > B) tmp = A, Q1.pop();
                else tmp = B, Q2.pop();
            }
            else {
                int A = q * x + a[P], B = (x - Q1.front().t) * q + Q1.front().w, C = (x - Q2.front().t) * q + Q2.front().w;
                int Max = max(A, max(B, C)); tmp = Max;
                if(Max == A) ++P;
                else if(Max == B) Q1.pop();
                else Q2.pop();
            }
        }
        return tmp;
    }
    int main() {
        n = read(), m = read(), q = read(), u = read(), v = read(), t = read();
        rep(i, 1, n) a[i] = read();
        sort(a + 1, a + n + 1, cmp);
        rep(i, 1, m) {
            int tmp = solve(i - 1); 
            if(i % t == 0) printf("%d ", tmp);
            Q1.push((node){i, 1ll * tmp * u / v}), Q2.push((node){i, tmp - 1ll * tmp * u / v});
        }
        puts("");
        rep(i, 1, n + m) {
            int tmp = solve(m);
            if(i % t == 0) printf("%d ", tmp);
        }
        return 0;
    }
    

    当每次操作涉及比大小以及添加一些数继续比大小的时候,往往加入的数会具有单调性,这样就不需要额外比较了。

  • 相关阅读:
    小问题也是大问题
    Java GC(2)
    Java GC(1)
    mac eclipse svn
    svn merge
    LTE,WiMAX与WIFI相关知识链接整理
    【LTE基础知识】承载相关概念介绍
    【LTE基础知识】LTE空口协议分析
    LTE基础知识
    Scapy学习2
  • 原文地址:https://www.cnblogs.com/Go7338395/p/13855190.html
Copyright © 2011-2022 走看看