首页 > 其他分享 >【题解】P4632 [APIO2018] 新家

【题解】P4632 [APIO2018] 新家

时间:2023-01-07 19:44:41浏览次数:48  
标签:P4632 nxt APIO2018 ch 商店 int 题解 void cnt

码力底下,思维迟钝,我该怎么办?

还是说这题太毒?

题意

给定一个 \(n\) 个商店,第 \(i\) 个商店的类型为 \(t_i\),在 \([a_i, b_i]\) 时间营业,位于位置 \(x_i\)。

定义某一时刻一种商店到某一个位置的距离为:该时刻营业的所有该种商店中到该位置的距离的最小值。

现在给定 \(q\) 个询问,每次询问在时刻 \(y_i\) 询问所有类型的商店到位置 \(x_i\) 的距离最大值。

\(1 \leq n, q \leq 3 \times 10^5\)

思路

线段树 + set 维护。

首先考虑对题目给出的位置和时间进行离散化。

然后可以考虑按照时间顺序维护操作,变成一个动态的维护问题。

拆一下操作,等价于维护:

  1. 在某一时刻,在某一位置插入一个商店

  2. 同 1,但删除商店

  3. 询问

询问显然具有单调性,所以可以考虑二分。

假设当前二分出的区间是 \([l, r]\),二分的判定问题是:判断 \([l, r]\) 中是否出现过所有颜色。

区间数颜色做法显然可以做,但是复杂度是假的。

我们发现只需要判断所有颜色是否都出现过,因此考虑更简单的做法。

令 \(nxt(r, c)\) 表示在位置 \(r\),类型为 \(c\) 的商店的后继,一种颜色在区间 \([l, r]\) 中出现过的充要条件是:\([1, l)\) 中所有位置的 \(nxt\) 不超过 \(r\).

那么对于多种颜色,只需要上线段树维护前缀 \(nxt\) 的最大值。

但是这题恶心的地方在于可能有多个商店在同一个位置。现在的问题是:插入和修改的操作应该怎么对应修改 \(nxt\)?

考虑维护类似链表的结构。不妨用一个 multiset 来维护 \(nxt\),当第一次插入某个 \(nxt\) 或删除完所有的 \(nxt\),就将对应位置的 \(nxt\) 集合相应地修改,\(nxt\) 集合的最值变化说明需要相应地修改线段树。

为了躲边界问题,可以先在序列开头加入所有类型的商店,并且在左右两端加两个边界端点。

注意离散化之后要相应地二分算距离。

代码

#include <cstdio>
#include <algorithm>
#include <set>
#include <map>
using namespace std;

const int maxn = 3e5 + 5;
const int maxq = 3e5 + 5;
const int sgt_sz = maxn << 2;

struct Query
{
    int x, c, t, p;
} opt[maxn * 3];

int n, k, q, m;
int len;
int ans[maxq];
int pos[maxn], sa[maxn];
int val[sgt_sz];
multiset<int, greater<int> > s[maxn];
map<int, int> cnt[maxn];

inline int read()
{
    int res = 0, flag = 1;
    char ch = getchar();
    while ((ch < '0') || (ch > '9'))
    {
        if (ch == '-') flag = -1;
        ch = getchar();
    }
    while ((ch >= '0') && (ch <= '9'))
    {
        res = res * 10 + ch - '0';
        ch = getchar();
    }
    return res * flag;
}

inline void write(int x)
{
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

void push_up(int k) { val[k] = max(val[k << 1], val[k << 1 | 1]); }

void update(int k, int l, int r, int p, int w)
{
    if (l == r)
    {
        val[k] = w;
        return;
    }
    int mid = (l + r) >> 1;
    if (p <= mid) update(k << 1, l, mid, p, w);
    else update(k << 1 | 1, mid + 1, r, p, w);
    push_up(k);
}

int query(int k, int l, int r, int p)
{
    if (r <= p) return val[k];
    int mid = (l + r) >> 1, res = 0;
    res = max(res, query(k << 1, l, mid, p));
    if (mid < p) res = max(res, query(k << 1 | 1, mid + 1, r, p));
    return res;
}

bool cmp(const Query& a, const Query& b) { return (a.t != b.t ? a.t < b.t : a.p < b.p); }

void _add(int x, int c)
{
    s[x].insert(c);
    if (c > sa[x]) sa[x] = c, update(1, 1, m, x, c);
}

void _del(int x, int c)
{
    s[x].erase(s[x].find(c));
    int curc = (*s[x].begin());
    if (curc < sa[x]) sa[x] = curc, update(1, 1, m, x, curc); 
}

void add(int x, int c)
{
    if (cnt[c].count(x)) { cnt[c][x]++; return; }
    auto it = cnt[c].upper_bound(x);
    int r = it -> first, l = (--it) -> first;
    _del(l, r), _add(x, r), _add(l, x);
    cnt[c].insert(make_pair(x, 1));
}

void del(int x, int c)
{
    if (cnt[c].count(x) && (cnt[c][x] > 1)) { cnt[c][x]--; return; }
    cnt[c].erase(x);
    auto it = cnt[c].upper_bound(x);
    int r = it -> first, l = (--it) -> first;
    _del(x, r), _del(l, x), _add(l, r);
}

void qry(int x, int p)
{
    int l = 0, r = 1e8 + 50;
    while (l < r)
    {
        int mid = (l + r) >> 1;
        int top = lower_bound(pos + 1, pos + m + 1, x - mid) - pos - 1;
        // printf("debug %d %d %d\n", x, mid, top);
        if (pos[query(1, 1, m, top)] <= x + mid) r = mid;
        else l = mid + 1;
    }
    // printf("debug %d\n", l);
    ans[p] = l;
}

int main()
{
    n = read(), k = read(), q = read();
    for (int i = 1, c; i <= n; i++)
    {
        pos[i] = read(), c = read();
        opt[++len] = (Query){pos[i], c, read(), 0};
        opt[++len] = (Query){pos[i], c, read() + 1, -1};
    }
    pos[n + 1] = -5e8, pos[n + 2] = 5e8;
    sort(pos + 1, pos + n + 3);
    m = unique(pos + 1, pos + n + 3) - pos - 1;
    for (int i = 1; i <= m; i++) s[i].insert(0);
    for (int i = 1; i <= k; i++)
    {
        cnt[i].insert(make_pair(1, 1));
        cnt[i].insert(make_pair(m, 1));
        s[1].insert(m);
    }
    sa[1] = m;
    update(1, 1, m, 1, m);
    for (int i = 1; i <= len; i++) opt[i].x = lower_bound(pos + 1, pos + m + 1, opt[i].x) - pos;
    for (int i = 1, x, t; i <= q; i++)
    {
        x = read(), t = read();
        opt[++len] = (Query){x, 0, t, i};
    }
    sort(opt + 1, opt + len + 1, cmp);
    for (int i = 1; i <= len; i++)
        if (opt[i].p == 0) add(opt[i].x, opt[i].c);
        else if (opt[i].p == -1) del(opt[i].x, opt[i].c);
        else qry(opt[i].x, opt[i].p);
    for (int i = 1; i <= q; i++) write(ans[i] > 1e8 ? -1 : ans[i]), putchar('\n');
    return 0;
}

标签:P4632,nxt,APIO2018,ch,商店,int,题解,void,cnt
From: https://www.cnblogs.com/lingspace/p/p4632.html

相关文章

  • 题解: Luogu P8894 「UOI-R1」求和
    题目链接:link前言我的一个学长在一次比赛中出了这道题,然后,我就把这道题切了其实这道题还是比较简单的,然后我就介绍一下我的比赛时的思路和做法30分做法根据标签我......
  • USACO 2022 Cu 题解
    USACO2022Cu题解AK用时:$3$小时$30$分钟。A-CowCollege原题FarmerJohn计划为奶牛们新开办一所大学!有$N$($1\leN\le10^5$)头奶牛可能会入学。每......
  • 【题解】P6074 最小路径
    太弱小了,失去了力量和精神。思路01分数规划+长链剖分优化dp.首先求形如\(\frac{\sum\limitsa_i}{\sum\limitsb_i}\)式子的最值,首先想到二分答案\(ans\),令每个......
  • [ABC257Ex] Dice Sum 2 题解
    [ABC257Ex]DiceSum2Solution目录[ABC257Ex]DiceSum2Solution更好的阅读体验戳此进入题面SolutionCodeUPD更好的阅读体验戳此进入题面存在$n$个正六面体骰......
  • Tsawke 的十月模拟赛 题解
    Tsawke的十月模拟赛题解T1这是一道比原来的T1更像T1的妙妙性质题原题是LG-P5497[LnOI2019SP]龟速单项式变换(SMT),原题范围$10^{18}$,我感觉没意思就加强到了$10......
  • LG-P3779 [SDOI2017] 龙与地下城 题解
    LG-P3779[SDOI2017]龙与地下城Solution目录LG-P3779[SDOI2017]龙与地下城Solution更好的阅读体验戳此进入题面SolutionCodeUPD更好的阅读体验戳此进入题面给定一......
  • AtCoder Beginner Contest 257 题解
    AtCoderBeginnerContest257Solution目录AtCoderBeginnerContest257Solution更好的阅读体验戳此进入题面链接题面Luogu链接abc跳了[ABC257D]JumpingTakahashi......
  • AtCoder Beginner Contest 258 题解
    AtCoderBeginnerContest258Solution目录AtCoderBeginnerContest258Solution更好的阅读体验戳此进入题面链接题面Luogu链接abcd跳了[ABC258E]PackingPotatoes......
  • [ABC250Ex] Trespassing Takahashi 题解
    [ABC250Ex]TrespassingTakahashiSolution目录[ABC250Ex]TrespassingTakahashiSolution更好的阅读体验戳此进入题面SolutionCodeUPD更好的阅读体验戳此进入题面给......
  • [ABC261E] Many Operations 题解
    [ABC261E]ManyOperationsSolution目录[ABC261E]ManyOperationsSolution更好的阅读体验戳此进入题面SolutionCodeUPD更好的阅读体验戳此进入题面给定正整数$X$......