题解 P4511 【[CTSC2015]日程管理】

· · 题解

更好的阅读体验

正题

一开始的时候显然第i天以前可以放i个任务是吧,然后考虑用一棵线段树维护这个数量,设每天的这个值为lev(i) 考虑在t这个截止时间位置放了一个任务,那(t,n)这个区间的 lev(i) 都要减去1。   

插入

设插入的终止时间为t,这个任务的价值为p。那如何插入呢?

至于这个集合怎么维护,显然线段树套个multiset就行了

代码

至于代码为什么这么长
当然是为了更好地装逼说明啦!  
记得点赞啊,我就没收过赞。。。  
下次一定的走开(bushi

#include <set>
#include <cstdio>
#include <utility>
#include <algorithm>

using namespace std;

#define R register
#define LL long long
#define IT multiset<int>::iterator

const int MAXN = 3e5 + 10;
const int inf = 1e9 + 10;

inline int read()
{
    char a = getchar();
    int x = 0, f = 1;
    for (; a > '9' || a < '0'; a = getchar())
        if (a == '-')
            f = -1;
    for (; a >= '0' && a <= '9'; a = getchar())
        x = x * 10 + a - '0';
    return x * f;
}

inline char getc()
{
    char a = getchar();
    while (a != 'A' && a != 'D')
        a = getchar();
    return a;
}

int n, m;
LL Ans;

struct Round
{
    int l, r, va;
};

class Tree_for_value
{
private:
    int tag[MAXN << 2];
    Round mn[MAXN << 2];
    inline int ls(int x);
    inline int rs(int x);
    inline void update(int x);
    inline void get(int x, int k);
    inline void pushdown(int x);

public:
    inline Round ask(int x, int l, int r, int Le, int Ri);
    inline void chg(int x, int l, int r, int Le, int Ri, int k);
    inline void build(int x, int l, int r);
} T1;

class Tree_for_mintask
{
private:
    multiset<int> st[MAXN << 2];
    pair<int, int> mn[MAXN << 2];
    inline int ls(int x);
    inline int rs(int x);
    inline void update(int x);

public:
    inline void build(int x, int l, int r);
    inline void insert(int x, int l, int r, int ad, int p);
    inline void del(int x, int l, int r, int ad, int p);
    inline pair<int, int> ask(int x, int l, int r, int Le, int Ri);
    inline int have(int x, int l, int r, int ad, int p);
} T2;

class Tree_for_maxtask
{
private:
    multiset<int> st[MAXN << 2];
    pair<int, int> mx[MAXN << 2];
    inline int ls(int x);
    inline int rs(int x);
    inline void update(int x);

public:
    inline void build(int x, int l, int r);
    inline void insert(int x, int l, int r, int ad, int p);
    inline void del(int x, int l, int r, int ad, int p);
    inline pair<int, int> ask(int x, int l, int r, int Le, int Ri);
} T3;

int main()
{
    freopen("d.in", "r", stdin);
    freopen("d.out", "w", stdout);
    n = read();
    m = read();
    T1.build(1, 1, n);
    T2.build(1, 1, n);
    T3.build(1, 1, n);
    char op;
    int t, p;
    while (m--)
    {
        op = getc();
        t = read();
        p = read();
        if (op == 'A')
        {
            Round pir = T1.ask(1, 1, n, t, n);
            if (pir.va > 0)
            {
                Ans += p;
                T1.chg(1, 1, n, t, n, -1);
                T2.insert(1, 1, n, t, p);
            }
            else
            {
                int id = pir.l;
                pair<int, int> tmp = T2.ask(1, 1, n, 1, id);
                if (tmp.first > p)
                    T3.insert(1, 1, n, t, p);
                else
                {
                    Ans += p - tmp.first;
                    T2.del(1, 1, n, tmp.second, tmp.first);
                    T3.insert(1, 1, n, tmp.second, tmp.first);
                    T1.chg(1, 1, n, tmp.second, n, 1);
                    T2.insert(1, 1, n, t, p);
                    T1.chg(1, 1, n, t, n, -1);
                }
            }
        }
        else
        {
            if (T2.have(1, 1, n, t, p) == 0)
                T3.del(1, 1, n, t, p);
            else
            {
                Ans -= p;
                T2.del(1, 1, n, t, p);
                T1.chg(1, 1, n, t, n, 1);
                Round tmp = T1.ask(1, 1, n, 1, n);
                int id = tmp.va <= 0 ? tmp.r : 0;
                if (id != n)
                {
                    pair<int, int> tmp = T3.ask(1, 1, n, id + 1, n);
                    if (tmp.first != -inf)
                    {
                        T3.del(1, 1, n, tmp.second, tmp.first);
                        T2.insert(1, 1, n, tmp.second, tmp.first);
                        T1.chg(1, 1, n, tmp.second, n, -1);
                        Ans += tmp.first;
                    }
                }
            }
        }
        printf("%lld\n", Ans);
    }
    return 0;
}

inline int Tree_for_value::ls(int x) { return x << 1; }
inline int Tree_for_value::rs(int x) { return x << 1 | 1; }
inline void Tree_for_value::update(int x)
{
    if (mn[ls(x)].va == mn[rs(x)].va)
    {
        mn[x].va = mn[ls(x)].va;
        mn[x].l = mn[ls(x)].l;
        mn[x].r = mn[rs(x)].r;
    }
    if (mn[ls(x)].va < mn[rs(x)].va)
        mn[x] = mn[ls(x)];
    if (mn[ls(x)].va > mn[rs(x)].va)
        mn[x] = mn[rs(x)];
}
inline void Tree_for_value::get(int x, int k)
{
    tag[x] += k;
    mn[x].va += k;
}
inline void Tree_for_value::pushdown(int x)
{
    if (tag[x])
    {
        get(ls(x), tag[x]);
        get(rs(x), tag[x]);
        tag[x] = 0;
    }
}
inline void Tree_for_value::build(int x, int l, int r)
{
    if (l == r)
    {
        mn[x] = {l, l, l};
        return;
    }
    int mid = l + r;
    mid >>= 1;
    build(ls(x), l, mid);
    build(rs(x), mid + 1, r);
    update(x);
}
inline void Tree_for_value::chg(int x, int l, int r, int Le, int Ri, int k)
{
    if (l >= Le && r <= Ri)
    {
        get(x, k);
        return;
    }
    pushdown(x);
    int mid = l + r;
    mid >>= 1;
    if (Le <= mid)
        chg(ls(x), l, mid, Le, Ri, k);
    if (Ri > mid)
        chg(rs(x), mid + 1, r, Le, Ri, k);
    update(x);
}
inline Round Tree_for_value::ask(int x, int l, int r, int Le, int Ri)
{
    if (l >= Le && r <= Ri)
        return mn[x];
    pushdown(x);
    int mid = l + r;
    mid >>= 1;
    Round ans;
    if (Le > mid)
        ans = ask(rs(x), mid + 1, r, Le, Ri);
    else if (Ri <= mid)
        return ans = ask(ls(x), l, mid, Le, Ri);
    else
    {
        Round lef = ask(ls(x), l, mid, Le, Ri), rig = ask(rs(x), mid + 1, r, Le, Ri);
        if (lef.va < rig.va)
            ans = lef;
        if (lef.va > rig.va)
            ans = rig;
        if (lef.va == rig.va)
        {
            ans.l = lef.l;
            ans.r = rig.r;
            ans.va = lef.va;
        }
    }
    update(x);
    return ans;
}

inline int Tree_for_mintask::ls(int x) { return x << 1; }
inline int Tree_for_mintask::rs(int x) { return x << 1 | 1; }
inline void Tree_for_mintask::update(int x)
{
    if (mn[ls(x)].first <= mn[rs(x)].first)
        mn[x] = mn[ls(x)];
    else
        mn[x] = mn[rs(x)];
}
inline void Tree_for_mintask::build(int x, int l, int r)
{
    if (l == r)
    {
        mn[x] = make_pair(inf, l);
        return;
    }
    int mid = l + r;
    mid >>= 1;
    build(ls(x), l, mid);
    build(rs(x), mid + 1, r);
    update(x);
}
inline void Tree_for_mintask::insert(int x, int l, int r, int ad, int p)
{
    if (l == r)
    {
        st[x].insert(p);
        mn[x].first = min(mn[x].first, p);
        return;
    }
    int mid = l + r;
    mid >>= 1;
    if (ad <= mid)
        insert(ls(x), l, mid, ad, p);
    else
        insert(rs(x), mid + 1, r, ad, p);
    update(x);
}
inline void Tree_for_mintask::del(int x, int l, int r, int ad, int p)
{
    if (l == r)
    {
        st[x].erase(st[x].find(p));
        if (st[x].size())
            mn[x].first = *st[x].begin();
        else
            mn[x].first = inf;
        return;
    }
    int mid = l + r;
    mid >>= 1;
    if (ad <= mid)
        del(ls(x), l, mid, ad, p);
    if (ad > mid)
        del(rs(x), mid + 1, r, ad, p);
    update(x);
}
inline pair<int, int> Tree_for_mintask::ask(int x, int l, int r, int Le, int Ri)
{
    if (l >= Le && r <= Ri)
        return mn[x];
    int mid = l + r;
    mid >>= 1;
    if (Le > mid)
        return ask(rs(x), mid + 1, r, Le, Ri);
    if (Ri <= mid)
        return ask(ls(x), l, mid, Le, Ri);
    pair<int, int> lef = ask(ls(x), l, mid, Le, Ri), rig = ask(rs(x), mid + 1, r, Le, Ri);
    if (lef.first <= rig.first)
        return lef;
    return rig;
}
inline int Tree_for_mintask::have(int x, int l, int r, int ad, int p)
{
    if (l == r)
        return st[x].find(p) != st[x].end();
    int mid = l + r;
    mid >>= 1;
    if (ad <= mid)
        return have(ls(x), l, mid, ad, p);
    else
        return have(rs(x), mid + 1, r, ad, p);
}

inline int Tree_for_maxtask::ls(int x) { return x << 1; }
inline int Tree_for_maxtask::rs(int x) { return x << 1 | 1; }
inline void Tree_for_maxtask::update(int x)
{
    if (mx[ls(x)].first > mx[rs(x)].first)
        mx[x] = mx[ls(x)];
    else
        mx[x] = mx[rs(x)];
}
inline void Tree_for_maxtask::build(int x, int l, int r)
{
    if (l == r)
    {
        mx[x] = make_pair(-inf, l);
        return;
    }
    int mid = l + r;
    mid >>= 1;
    build(ls(x), l, mid);
    build(rs(x), mid + 1, r);
    update(x);
}
inline void Tree_for_maxtask::insert(int x, int l, int r, int ad, int p)
{
    if (l == r)
    {
        st[x].insert(p);
        mx[x].first = max(mx[x].first, p);
        return;
    }
    int mid = l + r;
    mid >>= 1;
    if (ad <= mid)
        insert(ls(x), l, mid, ad, p);
    else
        insert(rs(x), mid + 1, r, ad, p);
    update(x);
}
inline void Tree_for_maxtask::del(int x, int l, int r, int ad, int p)
{
    if (l == r)
    {
        st[x].erase(st[x].find(p));
        if (st[x].size())
        {
            IT it = st[x].end();
            it--;
            mx[x].first = *it;
        }
        else
            mx[x].first = -inf;
        return;
    }
    int mid = l + r;
    mid >>= 1;
    if (ad <= mid)
        del(ls(x), l, mid, ad, p);
    if (ad > mid)
        del(rs(x), mid + 1, r, ad, p);
    update(x);
}
inline pair<int, int> Tree_for_maxtask::ask(int x, int l, int r, int Le, int Ri)
{
    if (l >= Le && r <= Ri)
        return mx[x];
    int mid = l + r;
    mid >>= 1;
    if (Le > mid)
        return ask(rs(x), mid + 1, r, Le, Ri);
    if (Ri <= mid)
        return ask(ls(x), l, mid, Le, Ri);
    pair<int, int> lef = ask(ls(x), l, mid, Le, Ri), rig = ask(rs(x), mid + 1, r, Le, Ri);
    if (lef.first > rig.first)
        return lef;
    return rig;
}