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;
}

  

原文地址:https://www.cnblogs.com/headboy2002/p/9375535.html