Petrozavodsk Summer Training Camp 2016H(多标记线段树)题解

Posted kirinsb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Petrozavodsk Summer Training Camp 2016H(多标记线段树)题解相关的知识,希望对你有一定的参考价值。

题意:

\(n\)个草,第\(0\)天种下,高度都为\(0\),每个草每天长高\(a_i\)。现给出\(q\)询问,每次给出第\(b\)天,然后把高于\(d\)的全削成\(d\),每次问你削下来的高度是多少。

思路:

能看出草的顺序和答案无关,那么按\(a_i\)排序,后面的草永远都比前面的高。然后线段树维护区间加,区间重置,区间询问。

代码:

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<bitset>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 5e5 + 5;
const int M = 50 + 5;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const ll MOD = 1000000007;

#define lson (rt << 1)
#define rson (rt << 1 | 1)
int n, m;
ll sum[maxn << 2], sumW[maxn << 2], Mw[maxn << 2], Max[maxn << 2];
ll t[maxn << 2], reset[maxn << 2];
//时间戳,重置
ll a[maxn];
void pushup(int rt)
    sum[rt] = sum[lson] + sum[rson];
    Max[rt] = Max[rson];
    Mw[rt] = Mw[rson];
    sumW[rt] = sumW[lson] + sumW[rson];

void pushdown(int rt, int l, int r)
    int m = (l + r) >> 1;
    if(reset[rt] != -1)
        reset[lson] = reset[rt];
        reset[rson] = reset[rt];
        t[lson] = 0;
        t[rson] = 0;
        Max[lson] = reset[rt];
        Max[rson] = reset[rt];
        sum[lson] = 1LL * reset[rt] * (m - l + 1);
        sum[rson] = 1LL * reset[rt] * (r - m);
        reset[rt] = -1;
    
    if(t[rt])
        sum[lson] += t[rt] * sumW[lson];
        sum[rson] += t[rt] * sumW[rson];
        Max[lson] += t[rt] * Mw[lson];
        Max[rson] += t[rt] * Mw[rson];
        t[lson] += t[rt];
        t[rson] += t[rt];
        t[rt] = 0;
    

void build(int l, int r, int rt)
    t[rt] = 0;
    reset[rt] = -1;
    if(l == r)
        sumW[rt] = Mw[rt] = a[l];
        sum[rt] = Max[rt] = 0;
        return;
    
    int m = (l + r) >> 1;
    build(l, m, lson);
    build(m + 1, r, rson);
    pushup(rt);

void _set(int L, int R, int l, int r, ll v, int rt)
    if(L <= l && R >= r)
        sum[rt] = 1LL * v * (r - l + 1);
        reset[rt] = v;
        Max[rt] = v;
        t[rt] = 0;
        return;
    
    pushdown(rt, l, r);
    int m = (l + r) >> 1;
    if(L <= m)
        _set(L, R, l, m, v, lson);
    if(R > m)
        _set(L, R, m + 1, r, v, rson);
    pushup(rt);

void add(int L, int R, int l, int r, ll v, int rt)
    if(L <= l && R >= r)
        sum[rt] += sumW[rt] * v;
        t[rt] += v;
        Max[rt] += Mw[rt] * v;
        return;
    
    pushdown(rt, l, r);
    int m = (l + r) >> 1;
    if(L <= m)
        add(L, R, l, m, v, lson);
    if(R > m)
        add(L, R, m + 1, r, v, rson);
    pushup(rt);

ll querysum(int L, int R, int l, int r, int rt)
    if(L <= l && R >= r)
        return sum[rt];
    
    pushdown(rt, l, r);
    int m = (l + r) >> 1;
    ll ret = 0;
    if(L <= m)
        ret += querysum(L, R, l, m, lson);
    if(R > m)
        ret += querysum(L, R, m + 1, r, rson);
    return ret;

int queryMore(int l, int r, ll v, int rt)
    if(l == r)
        return Max[rt] > v? l : -1;
    
    pushdown(rt, l, r);
    int m = (l + r) >> 1;
    if(Max[lson] > v)
        return queryMore(l, m, v, lson);
    else
        return queryMore(m + 1, r, v, rson);

int main()
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    sort(a + 1, a + n + 1);
    build(1, n, 1);
    ll u, v, pre = 0;
    while(m--)
        scanf("%lld%lld", &u, &v);
        add(1, n, 1, n, u - pre, 1);
        int pos = queryMore(1, n, v, 1);
        if(pos == -1) puts("0");
        else
            ll ret = querysum(pos, n, 1, n, 1);
            ret = ret - 1LL * v * (n - pos + 1);
            printf("%lld\n", ret);
            _set(pos, n, 1, n, v, 1);
        
        pre = u;
    
    return 0;

以上是关于Petrozavodsk Summer Training Camp 2016H(多标记线段树)题解的主要内容,如果未能解决你的问题,请参考以下文章

Petrozavodsk Summer-2016. Warsaw U Contest, XVI Open Cup Onsite.

Petrozavodsk Summer Training Camp 2016H(多标记线段树)题解

2018-2019 Summer Petrozavodsk Camp, Oleksandr Kulkov Contest 2解题报告

2020 Petrozavodsk Winter Camp, Jagiellonian U Contest 部分题解

2020 Petrozavodsk Winter Camp, Jagiellonian U Contest 部分题解

Petrozavodsk Winter-2019. Yandex Cup 2019.