Bzoj4548 小奇的糖果(鏈表+樹狀數組)

題面

Bzojphp

題解

很顯然,咱們只須要考慮單獨取線段上方的狀況,對於下方的把座標取反再作一遍便可(由於咱們只關心最終的答案)數組

創建樹狀數組維護一個橫座標區間內有多少個點,維護雙向鏈表實現查詢一個點左(右)橫座標最大(小)的與它相同的點。code

首先枚舉沒有取到的顏色,找出全部不包含這種顏色的區間,更新答案。get

接着考慮兩個相同顏色的點的貢獻,按照縱座標從大到小枚舉全部的點,分別在樹狀數組和雙向鏈表中刪除當前點,並利用這個點左右兩邊和它顏色相同的點之間的區間內點的個數更新答案。string

#include <cstdio>
#include <cstring>
#include <algorithm>
using std::min; using std::max;
using std::sort; using std::swap;
using std::unique; using std::lower_bound;
typedef long long ll;

template<typename T>
void read(T &x) {
    int flag = 1; x = 0; char ch = getchar();
    while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
}

const int N = 1e5 + 10;
int T, n, K, x[N], ans;
struct data { int x, y, z, id; } p[N];
int disc[N], t[N];//樹狀數組
int last[N], l[N], r[N];//雙向鏈表

void add (int x, int y) { while(x <= n + 1) t[x] += y, x += (x & -x); }
int query (int x) { int y = 0; while(x) y += t[x], x -= (x & -x); return y; }
inline bool cmpx(const data &a, const data &b) { return a.x < b.x; }
inline bool cmpy(const data &a, const data &b) { return a.y < b.y; }
void update(int l, int r) {
    if(l > r) return ;
    int tmp = query(r) - query(l - 1);
    ans = max(tmp, ans);
}

void doit () {
    x[0] = 0, x[n + 1] = n + 1;
    memset(last, 0, sizeof last), memset(t, 0, sizeof t);
    sort(&p[1], &p[n + 1], cmpx);
    for(int i = 1; i <= n; ++i) add(p[i].x, 1);
    for(int i = 1; i <= n; ++i) {
        int t = p[i].id, L= last[p[i].z];
        l[t] = L, r[t] = n + 1;
        if(L) r[L] = t;
        update(x[L] + 1, x[t] - 1);
        last[p[i].z] = t;
    }
    for(int i = 1; i <= K; ++i)
        update(x[last[i]] + 1, n + 1);
    sort(&p[1], &p[n + 1], cmpy);
    for(int i = 1, j = 1; i <= n; ++i) {
        int t = p[i].id;
        while(j <= n && p[j].y == p[i].y) add(p[j].x, - 1), ++j;
        l[r[t]] = l[t], r[l[t]] = r[t];
        update(x[l[t]] + 1, x[r[t]] - 1);
    }
}

int main () {
    read(T);
    while(T--) {
        ans = 0, read(n), read(K); int m = n;
        for(int i = 1; i <= n; ++i)
            read(p[i].x), read(p[i].y), read(p[i].z), p[i].id = i;
        for(int i = 1; i <= n; ++i)
            disc[i] = p[i].x;
        sort(&disc[1], &disc[m + 1]), m = unique(&disc[1], &disc[m + 1]) - disc - 1;
        for(int i = 1; i <= n; ++i) {
            p[i].x = lower_bound(&disc[1], &disc[m + 1], p[i].x) - disc;
            x[i] = p[i].x;
        }
        doit(); for(int i = 1; i <= n; ++i) p[i].y = -p[i].y; doit();
        printf("%d\n", ans);
    }
    return 0;
}
相關文章
相關標籤/搜索