zoukankan      html  css  js  c++  java
  • UVALive 6261 Jewel heist

    题意:珠宝大盗Arsen Lupin偷珠宝。在展厅内,每颗珠宝有个一个坐标为(xi,yi)和颜色ci。

    Arsen Lupin发明了一种设备,可以抓取平行x轴的一条线段下的所有珠宝而不触发警报,

    唯一的限制是抓取的珠宝不能不能有所有的m种颜色。询问能抓取的最大珠宝数量。

    分析:要决策的东西有两个,一是这条线段的y坐标,二是线段的x的范围。

    枚举线段的y坐标,线段宽度要保证下方不能有所有的颜色,这需要知道颜色的关于x的坐标信息,

    为了x的坐标信息的重复利用,从小到大枚举y。

    对于一个固定的yi,怎么找到合适的区间呢?一个简单且正确的想法是枚举不要的颜色,

    对于每种不要的颜色,只要选择不包含这种颜色的区间就可以保证符号要求了。

    但是这样做太慢了,枚举颜色是O(n)的。

    幸运的是,这里面有大量的重复计算,在枚举yi-1的时候,有很多的区间是不会变的,已经计算过的了,

    只要枚举发生了改变的区间。

    关于颜色的区间信息可以用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
    ", ans);
    }
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        int T; scanf("%d",&T);
        while(T--) solve();
        return 0;
    }
  • 相关阅读:
    SqlServer 查看数据库中所有存储过程
    SqlServer 查看数据库中所有视图
    SqlServer 查询表的详细信息
    SqlServer 遍历修改字段长度
    net core 操作Redis
    Tuning SharePoint Workflow Engine
    Open With Explorer
    Download language packs for SharePoint 2013
    Change Maximum Size For SharePoint List Template when Saving
    Six ways to store settings in SharePoint
  • 原文地址:https://www.cnblogs.com/jerryRey/p/5043776.html
Copyright © 2011-2022 走看看