AcWing 133. 蚯蚓

AcWing 133. 蚯蚓

思考

朴素版的暴力写法就是全部遍历,每次操作后再排序。

而聪明一点的人就用单调队列,但是m的范围是七百万,这是非用线性算法不可(堆每次维护是\(O(n log n)\)

但是突破口在哪里?其实你用优先队列的时候已经想到了。

既然题目说除了切开的蚯蚓,其他蚯蚓每过一秒长q的长度,那么正常人是不会每操作一次遍历一遍堆的,一定是把所有累加的q(总和是\(i * q\))放在外面,等到要用的时候再加上。

这就是保留偏移量的方法,因为\(x_1 > x_2,那么一定存在 x_1 - delta > x_2 - delta\)

推导

只能从优化数据结构入手了。但是不挖掘性质的话,最优解法至此结束。

我们先看切开蚯蚓后的情况,先从简单的入手,再一步一步推进(正解往往从猜测中出现)。

下文的所有情况,都是建立在正确合法的顺序之上。
假设现在有一只长度为\(x_1\)的蚯蚓要被切开,还有一只\(x_2\)的蚯蚓在下一秒要被切开。

那么必定有\(x_1 >= x_2\)

那么第一秒的时候,切开的两段蚯蚓和x2的长度分别是:

\[px_1 \ , \ x_1 - px_1 \ , \ x_2 + q \]

第二秒的时候,x1切开的两段蚯蚓和x2切开的两段蚯蚓长度分别是:

\[px_1 + q \ , \ x_1 - px_1 + q \ , \ px_2 + pq \ , \ x + q - px_2 - pq \]

我们会发现,1和3式很像,2和4式很像。

那么我们就拿切开的蚯蚓的左半边和左半边比较,右半边亦是如此,发现先切开的蚯蚓的同半边一定比后切开的蚯蚓的同半边要大,还未切开的蚯蚓显然也是如此

如果时间延伸成:一只长度为\(x_1\)的蚯蚓要被切开,还有一只\(x_2\)的蚯蚓在下k秒被切开,那么规律也是一样的。

最有力的性质被找到了,也就是3种蚯蚓呈单调递减,那么就意味着每次操作之后省去了排序的时间,时间复杂度\(O(m)\)
这个活交给队列来干,队列先进先出恰好符合。

但是有一点:三种蚯蚓之间没有明确的大小关系。那么只需要每次操作的时候取出三个队头,比较其大小再使用。
最后一点:十年OI一场空,不开long long见祖宗

100 pts

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 100010;
typedef long long ll;
ll n, m, q, u, v, t;
ll a[N];
queue<ll> q1, q2, q3;

int get(int dt)
{
    ll a = -1, b = -1, c = -1;
    if(q1.size()) a = q1.front() + q * dt;
    if(q2.size()) b = q2.front() + q * dt;
    if(q3.size()) c = q3.front() + q * dt;
    
    ll res = max(a, max(b, c));
    
    if(res == a) q1.pop();
    else if(res == b) q2.pop();
    else if(res == c) q3.pop();
    return res;
}

int main()
{
    cin >> n >> m >> q >> u >> v >> t;
    for(int i = 1; i <= n; i ++ ) cin >> a[i];
    
    sort(a + 1, a + n + 1), reverse(a + 1, a + n + 1);
    for(int i = 1; i <= n; i ++ ) q1.push(a[i]);
    
    for(int i = 1; i <= m; i ++ )
    {
        ll x = get(i - 1);
        if(i % t == 0) cout << x << ' ';
        
        ll a = x * u / v; ll b = x - a;
        q2.push(a - i * q);
        q3.push(b - i * q);
    }
    cout << endl;
    
    for(int i = 1; i <= n + m; i ++ )
    {
        ll x = get(m);
        if(i % t == 0) cout << x << ' ';
    }
    
    return 0;
}
posted @ 2023-01-29 21:32  Sankano  阅读(27)  评论(0编辑  收藏  举报