「BZOJ4548」小奇的糖果

传送门
memset0好评

解题思路

比较恶心的一道数据结构题
看一眼题面,马上想到离散化。
然后将一维排序,另一维用树状数组或者线段树维护。
然后就没思路了
发现一个性质:
不包含所有的颜色,当然要使得只有一种不被选的颜色。
那么我们可以对每一种颜色开一个 \(\text{set}\) ,这样就可以比较方便地找到,某个时刻一种颜色的覆盖范围。
对于向上和向下,只要跑正反两边就好了。

细节注意事项

  • 咕咕咕

参考代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#include <set>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while (!isdigit(c)) f |= (c == '-'), c = getchar();
    while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
    s = f ? -s : s;
}

const int _ = 100010;

int t[_];
set < int > s[_];
set < int > ::iterator it;
int n, m, ans, X[_]; struct node{ int x, y, z; }p[_];

inline bool cmp(const node& a, const node& b) { return a.y < b.y; }

inline int lb(int x) { return x & -x; }

inline void update(int x) { for (rg int i = x; i <= n; i += lb(i)) ++t[i]; }

inline int query(int x) { int res = 0; for (rg int i = x; i >= 1; i -= lb(i)) res += t[i]; return res; }

inline void solve() {
    memset(t, 0, sizeof t);
    for (rg int i = 1; i <= m; ++i) s[i].clear(), s[i].insert(0), s[i].insert(n + 1);
    for (rg int i = 1, j = 1; i <= n; i = j) {
        while (j <= n && p[i].y == p[j].y) ++j;
        for (rg int k = i; k < j; ++k) {
            int r = *s[p[k].z].lower_bound(p[k].x) - 1;
            int l = *--s[p[k].z].upper_bound(p[k].x);
            ans = max(ans, query(r) - query(l));
        }
        for (rg int k = i; k < j; ++k) update(p[k].x), s[p[k].z].insert(p[k].x);
    }
    for (rg int x, i = 1; i <= m; ++i)
        for (it = s[i].begin(); it != s[i].end(); )
            x = *it, ans = max(ans, query(*++it - 1) - query(x));
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
#endif
    int T; read(T);
    while (T--) {
        read(n), read(m);
        for (rg int i = 1; i <= n; ++i)
            read(p[i].x), read(p[i].y), read(p[i].z), X[i] = p[i].x;
        sort(X + 1, X + n + 1), sort(p + 1, p + n + 1, cmp);
        for (rg int i = 1; i <= n; ++i)
            p[i].x = lower_bound(X + 1, X + n + 1, p[i].x) - X;
        ans = 0;
        solve(), reverse(p + 1, p + n + 1), solve();
        printf("%d\n", ans);
    }
    return 0;
}

完结撒花 \(qwq\)

猜你喜欢

转载自www.cnblogs.com/zsbzsb/p/11745907.html