UVALive 6261 Jewel heist

題意:珠寶大盜Arsen Lupin偷珠寶。在展廳內,每顆珠寶有個一個座標爲(xi,yi)和顏色ci。c++

Arsen Lupin發明了一種設備,能夠抓取平行x軸的一條線段下的全部珠寶而不觸發警報,spa

惟一的限制是抓取的珠寶不能不能有全部的m種顏色。詢問能抓取的最大珠寶數量。code

分析:要決策的東西有兩個,一是這條線段的y座標,二是線段的x的範圍。blog

枚舉線段的y座標,線段寬度要保證下方不能有全部的顏色,這須要知道顏色的關於x的座標信息,ci

爲了x的座標信息的重複利用,從小到大枚舉y。it

對於一個固定的yi,怎麼找到合適的區間呢?一個簡單且正確的想法是枚舉不要的顏色,class

對於每種不要的顏色,只要選擇不包含這種顏色的區間就能夠保證符號要求了。sort

可是這樣作太慢了,枚舉顏色是O(n)的。di

幸運的是,這裏面有大量的重複計算,在枚舉yi-1的時候,有不少的區間是不會變的,已經計算過的了,auth

只要枚舉發生了改變的區間。

關於顏色的區間信息能夠用set保存,在枚舉的區間合法的狀況下只是一個區間詢問單點更新可用BIT,下標範圍須要離散。

/*********************************************************
*          ----------------------------                  *
*   author AbyssalFish                                   *
**********************************************************/
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int maxn = 2e5+5;

set<int> S[maxn];

int x[maxn],y[maxn],c[maxn];
int r[maxn], xs[maxn];

int *cmp_c;
bool cmp_id(int i,int j){ return cmp_c[i] < cmp_c[j]; }

int C[maxn];
int ns;

void add(int x)
{
    while(x <= ns){
        C[x]++; x += x&-x;
    }
}

int sum(int x)
{
    int re = 0;
    while(x > 0){
        re += C[x]; x &= x-1;
    }
    return re;
}


void solve()
{
    int n, m, i, j, k;
    scanf("%d%d",&n,&m);
    for(i = 0; i < n; i++) {
        scanf("%d%d%d",x+i,y+i,c+i);
        r[i] = i;
    }

    cmp_c = x;
    sort(r,r+n,cmp_id);
    ns = 1;
    xs[r[0]] = ns;
    for(i = 1; i < n; i++){
        xs[r[i]] = (x[r[i]] == x[r[i-1]]) ? ns:++ns;
    }

    for(i = 1; i <= m; i++){
        S[i].clear();
        S[i].insert(0);
        S[i].insert(ns+1);
    }

    cmp_c = y;
    for(i = 0; i < n; i++) r[i] = i;
    sort(r,r+n,cmp_id);

    memset(C+1,0,sizeof(int)*ns);

    int ans = 0, p, q, cur_y;
    for(i = 0; i < n; i = k){
        cur_y = y[r[i]];
        for(j = i; j < n && y[k = r[j]] == cur_y; j++){
            auto it = S[c[k]].lower_bound(xs[k]);
            p = *it-1;
            q = *--it;
            if(p > q)
                ans = max(ans,sum(p)-sum(q));
        }
        k = j;
        while(--j >= i){
            p = r[j];
            S[c[p]].insert(xs[p]);
            add(xs[p]);
        }
    }
    for(i = 1; i <= m; i++){
        auto it = S[i].begin();
        q = 0;
        for(it++; it != S[i].end(); it++){
            p = *it-1;
            if(p > q) ans = max(ans, sum(p) - sum(q));
            q = *it;
        }
    }
    printf("%d\n", ans);
}

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    int T; scanf("%d",&T);
    while(T--) solve();
    return 0;
}
相關文章
相關標籤/搜索