• luogu3157 动态逆序对


    题目大意

      给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

    思路

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int MAX_INDEX = 100010, MAX_MAXVAL = MAX_INDEX, MAX_DEL_CNT = 50010, MAX_NODE = 9e6;
    int Queries[MAX_DEL_CNT];
    long long Ans[MAX_DEL_CNT];
    int TotIndex, TotDelCnt, MaxVal;
    
    struct Data
    {
        int Index, Val, AddTime;
    
        bool operator < (const Data& a) const
        {
            return AddTime < a.AddTime;
        }
    }_datas[MAX_INDEX];
    
    struct Node
    {
        int lSonId, rSonId;
        int Cnt;
    
        Node() :lSonId(0), rSonId(0), Cnt(0) {}
    }_nodes[MAX_NODE];
    int _vCount;
    
    struct RangeTree
    {
    private:
        int RootId;
    
        Node *NewNode()
        {
            return _nodes + ++_vCount;
        }
    
        void Update(int &curId, int l, int r, int p, int delta)
        {
            Node *cur = _nodes + curId;
            if (!curId)
            {
                cur = NewNode();
                curId = cur - _nodes;
            }
            cur->Cnt += delta;
            if (l == r)
                return;
            int mid = (l + r) / 2;
            if (p <= mid)
                Update(cur->lSonId, l, mid, p, delta);
            if (p > mid)
                Update(cur->rSonId, mid + 1, r, p, delta);
        }
    
        long long QueryPrefix(int k)
        {
            Node *cur = RootId ? _nodes + RootId : NULL;
            int l = 1, r = MaxVal;
            long long ans = 0;
            while (l < r && cur)
            {
                int mid = (l + r) / 2;
                if (k >= mid)
                {
                    ans += cur->lSonId ?_nodes[cur->lSonId].Cnt :0;
                    cur = cur->rSonId ? _nodes + cur->rSonId : NULL;
                    l = mid + 1;
                }
                else
                {
                    cur = cur->lSonId ? _nodes + cur->lSonId:NULL;
                    r = mid;
                }
            }
            return ans;
        }
    
        long long QuerySuffix(int k)
        {
            Node *cur = RootId ? _nodes + RootId : NULL;
            if (!cur)
                return 0;
            return cur->Cnt - QueryPrefix(k-1);
        }
    
    public:
        RangeTree() :RootId(0) {}
    
        void Update(int p, int delta)
        {
            if (p < 1 || p > MaxVal)
                return;
            Update(RootId, 1, MaxVal, p, delta);
        }
    
        long long Query(int l, int r)
        {
            if (l > r)
                return 0;
            long long ans1 = 0;
            if (l == 1)
            {
                ans1 = QueryPrefix(r);
                return ans1;
            }
            else if (r == MaxVal)
            {
                ans1= QuerySuffix(l);
                return ans1;
    
            }
            else
                return 0;
        }
    };
    
    struct BinaryTree
    {
    private:
        RangeTree C[MAX_MAXVAL];
        int N;
    
        int Lowbit(int x)
        {
            return x & -x;
        }
    
    public:
        BinaryTree(int n) :N(n) {}
    
        void Update(int p, int delta)
        {
            if (p < 0)
                return;
            while (p <= N)
            {
                C[p].Update(delta, 1);
                p += Lowbit(p);
            }
        }
    
        long long Query(int p, long long(*getVal)(RangeTree&, int), int cKey)
        {
            long long ans = 0;
            while (p > 0)
            {
                ans += getVal(C[p], cKey);
                p -= Lowbit(p);
            }
            return ans;
        }
    }*a;
    
    long long Range_GetIdGreaterCnt(RangeTree& tree, int k)
    {
        return tree.Query(k + 1, MaxVal);
    }
    
    long long Range_GetIdLesserCnt(RangeTree& tree, int k)
    {
        return tree.Query(1, k - 1);
    }
    
    void Update(Data& data)
    {
        a->Update(data.Val, data.Index);
    }
    
    long long Query(Data& data)
    {
        return a->Query(data.Val - 1, Range_GetIdGreaterCnt, data.Index) +
            a->Query(MaxVal, Range_GetIdLesserCnt, data.Index) - a->Query(data.Val, Range_GetIdLesserCnt, data.Index);
    }
    
    int main()
    {
        scanf("%d%d", &TotIndex, &TotDelCnt);
        MaxVal = TotIndex;
        static int Match[MAX_INDEX];
        for (int i = 1; i <= TotIndex; i++)
        {
            _datas[i].Index = i;
            scanf("%d", &_datas[i].Val);
            Match[_datas[i].Val] = i;
        }
        int addTime = TotDelCnt;
        for (int i = 1; i <= TotDelCnt; i++)
        {
            int delId;
            scanf("%d", &delId);
            _datas[Match[delId]].AddTime = addTime--;
        }
    
        sort(_datas + 1, _datas + TotIndex + 1);
        a = new BinaryTree(MaxVal);
        long long tempAns = 0;
        for (int i = 1; i <= TotIndex - TotDelCnt; i++)
        {
            Update(_datas[i]);
            tempAns += Query(_datas[i]);
        }
        for (int i = TotIndex - TotDelCnt + 1; i <= TotIndex; i++)
        {
            Update(_datas[i]);
            Ans[_datas[i].AddTime] = tempAns += Query(_datas[i]);
        }
    
        for (int i = TotDelCnt; i >= 1; i--)
            printf("%lld
    ", Ans[i]);
        return 0;
    }
    

      

  • 相关阅读:
    AGC 018E.Sightseeing Plan(组合 DP)
    BZOJ.4767.两双手(组合 容斥 DP)
    AGC 001E.BBQ Hard(组合 DP)
    洛谷.3960.列队(线段树/树状数组)
    Codeforces Round #514 (Div. 2)
    10.4 正睿国庆集训测试 青岛
    Codeforces.264E.Roadside Trees(线段树 DP LIS)
    BZOJ.4653.[NOI2016]区间(线段树)
    Ansible安装部署以及常用模块详解
    Linux系统诊断必备技能之二:tcpdump抓包工具详解
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9375535.html
Copyright © 2020-2023  润新知