BZOJ 3262: 陌上花开

经典的三维偏序问题,CDQ分治一维,树状数组维护一维
注意完全相等的情况

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 2e5 + 10;

struct node {
    int id;
    int si, ci, mi;
    int cnt;
    void input(int id)
    {
        this->id = id;
        scanf("%d %d %d", &si, &ci, &mi);
        this->cnt = 0;
    }
    bool operator < (const node &other) const
    {
        if (si != other.si) return si > other.si;
        if (ci != other.ci) return ci > other.ci;
        return mi > other.mi;
    }
}arr[maxn], brr[maxn], tarr[maxn];

int n, k;
int ans[maxn];
int tot[maxn];

namespace BIT
{
    int a[maxn];
    void Init()
    {
        memset(a, 0, sizeof a);
    }
    void update(int x, int val)
    {
        for (; x <= k; x += x & -x)
            a[x] += val;
    }
    int query(int x)
    {
        int res = 0;
        for (; x > 0; x -= x & -x)
            res += a[x];
        return res;
    }
    int query(int l, int r)
    {
        return query(r) - query(l - 1);
    }
}

int cmp(node a, node b)
{
    return a.ci < b.ci;
}

void CDQ(int l, int r)
{
    if (l > r) return;
    if (l == r)
    {
        ans[arr[l].id] += arr[l].cnt - 1;
        return;
    }
    int mid = (l + r) >> 1;
    for (int i = l; i <= r; ++i) tarr[i] = arr[i];
    sort(tarr + l, tarr + mid + 1, cmp);
    sort(tarr + mid + 1, tarr + r + 1, cmp);
    int L = mid + 1, R = mid + 1;
    for (int i = l; i <= mid; ++i)
    {
        while (R <= r && tarr[i].ci >= tarr[R].ci)
        {
            BIT::update(tarr[R].mi, tarr[R].cnt);
            ++R;
        }
        ans[tarr[i].id] += BIT::query(tarr[i].mi);
    }
    while (L < R)
    {
        BIT::update(tarr[L].mi, -tarr[L].cnt);
        ++L;
    }
    CDQ(l, mid);
    CDQ(mid + 1, r);
}

void RUN()
{
    while (~scanf("%d %d", &n, &k))
    {
        BIT::Init();
        memset(ans, 0, sizeof ans);
        memset(tot, 0, sizeof tot);
        for (int i = 1; i <= n; ++i) brr[i].input(i);
        sort(brr + 1, brr + 1 + n);
        int cnt = 0;
        for (int i = 1; i <= n; ++i)
        {
            if (i != 1 && brr[i - 1].si == brr[i].si && brr[i - 1].ci == brr[i].ci && brr[i - 1].mi == brr[i].mi) arr[cnt].cnt++;
            else arr[++cnt] = brr[i], arr[cnt].id = cnt, arr[cnt].cnt = 1;
        }
        CDQ(1, cnt);
        for (int i = 1; i <= cnt; ++i)
        {
            tot[ans[i]] += arr[i].cnt;
        }
        for (int i = 0; i < n; ++i) printf("%d\n", tot[i]);
    }
}

int main()
{
#ifdef LOCAL_JUDGE
    freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE

    RUN();

    return 0;
}
View Code

 

posted @ 2019-04-12 22:49  薛37  阅读(82)  评论(0编辑  收藏  举报