zoukankan      html  css  js  c++  java
  • luogu2161 [SHOI2009]会场预约

    题目大意

      随着时间的推移这里有几个任务对应着一段区间。每次要将任务安到时间线上时,要把时间线上已有的与该任务对应区间有交集的区间对应的任务删去。求每次删去的区间个数,以及整个时间线上有几个任务。时间线长度m<=100000,任务个数n<=200000

    题解

      对于一个新加入的区间,我们要从右往左枚举每一个左端点小于等于新区间右端点的任务,直到枚举到了一个任务其右端点小于新任务的左端点。对于每一个要枚举到的任务,我们要尽可能缩小找到它的时间复杂度。于是建立一个权值树状数组,key值时间,值是左端点位于该点的任务个数。其维护的就是左端点个数的前缀和了,它满足单调性。左端点所在的地方就是权值增加的地方,而对于一个新区间,新区间右端点所在的权值前缀和就是离该点左侧的第一个左端点所在位置的权值前缀和。于是我们可以轻松用LowerBound得到区间,就这样不断删除二分删除二分(我们对于每一个左端点整一个数组维护其对应的右端点),直到有一个区间右端点小于新区间左端点为止。极端复杂度$O(n^2 log m)$。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int MAX_LEN = 100010, TotLen = 100000;
    int LmatchR[MAX_LEN];
    
    struct BST
    {
    private:
        int C[MAX_LEN];
        int N;
    
        int Lowbit(int x)
        {
            return x & -x;
        }
    
    public:
        BST(int n):N(n){}
    
        int Query(int p)
        {
            int ans = 0;
            while (p > 0)
            {
                ans += C[p];
                p -= Lowbit(p);
            }
            return ans;
        }
    
        void Update(int p, int delta)
        {
            while (p <= N)
            {
                C[p] += delta;
                p += Lowbit(p);
            }
        }
    }g(TotLen);
    
    int PrefixFind;
    
    bool GtPrefixFind(int k)
    {
        return g.Query(k) >= PrefixFind;
    }
    
    int LowerBound(int l, int r, bool(*InRange)(int))
    {
        if (!InRange(r))
            return -1;
        while (l < r)
        {
            int mid = (l + r) / 2;
            if (InRange(mid))
                r = mid;
            else
                l = mid + 1;
        }
        return l;
    }
    
    int main()
    {
        int qCnt;
        scanf("%d", &qCnt);
        while (qCnt--)
        {
            char op;
            int newL, newR, curL, delCnt;
            scanf("
    %c", &op);
            switch (op)
            {
            case 'A':
                scanf("%d%d", &newL, &newR);
                delCnt = 0;
                while (true)
                {
                    PrefixFind = g.Query(newR);
                    if (PrefixFind == 0)
                        break;
                    curL = LowerBound(1, newR, GtPrefixFind);
                    if (curL == -1)
                        break;
                    if (LmatchR[curL] >= newL)
                    {
                        delCnt++;
                        g.Update(curL, -1);
                    }
                    else
                        break;
                }
                g.Update(newL, 1);
                LmatchR[newL] = newR;
                printf("%d
    ", delCnt);
                break;
            case 'B':
                printf("%d
    ", g.Query(TotLen));
                break;
            }
        }
    }
    

      

  • 相关阅读:
    【树链剖分】【线段树】bzoj2157 旅游
    【高斯消元】【异或方程组】poj1222 EXTENDED LIGHTS OUT
    【树链剖分】【线段树】bzoj3626 [LNOI2014]LCA
    【dfs】bzoj3563 DZY Loves Chinese
    【高斯消元】【异或方程组】【bitset】bzoj1923 [Sdoi2010]外星千足虫
    【高斯消元】bzoj1013 [JSOI2008]球形空间产生器sphere
    【博弈论】bzoj1115 [POI2009]石子游戏Kam
    【最近公共祖先】【树链剖分】CODEVS 1036 商务旅行
    【块状树】【博弈论】bzoj3729 Gty的游戏
    【博弈论】【SG函数】bzoj1777 [Usaco2010 Hol]rocks 石头木头
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9474322.html
Copyright © 2011-2022 走看看