244. 谜一样的牛

题解参考AcWing 244. 谜一样的牛 - AcWing

另外,起初我以为是要对身高数组直接建立树状数组来求解问题,但是这样做的信息太少,根本不能得到答案;

实际上,树状数组是用来辅助我们求身高的,我们需要构造一个树状数组,来帮助我们确认牛的身高。

很多数据结构类的问题也是这样,不直接对所求问题建立数据结构,而是利用某些特殊的已知信息来建立数据结构,帮助我们求解问题。

1.二分

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#define For(i, j, n) for(int i = j ; i <= n ; ++i)
using namespace std;

const int N = 1e5 + 5;

int lowbit(int x)
{
    return x & (-x);
}

int n, a[N], tr[N], h[N];

void modify(int k, int x)
{
    for(int i = k; i <= n; i += lowbit(i))
        tr[i] += x;
}

int query(int k)
{
    int res = 0;
    for(int i = k; i; i -= lowbit(i))
        res += tr[i];
    return res;
}

int find(int x)
{
    int l = 1, r = n;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(query(mid) >= x) r = mid;
        else l = mid + 1;
    }
    return l;
}

void init()
{
    for(int i = 1; i <= n; i++)
        modify(i, 1);
}

int main()
{
    scanf("%d", &n);
    for(int i = 2; i <= n; i++)
        scanf("%d", &a[i]);
    init();
    for(int i = n; i >= 1; i--)
    {
        int pos = find(a[i] + 1);
        h[i] = pos;
        modify(pos, -1);
    }
    for(int i = 1; i <= n; i++)
        printf("%d\n", h[i]);
    return 0;
}

2.由于这道题的特殊性,(所有涉及到的区间都是我们已经预设好的区间)我们还可以用倍增法来求解

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <cmath>
#define For(i, j, n) for (int i = j; i <= n; ++i)
using namespace std;

const int N = 1e5 + 5;

int lowbit(int x)
{
    return x & (-x);
}

int n, a[N], tr[N], h[N];

void modify(int k, int x)
{
    for (int i = k; i <= n; i += lowbit(i))
        tr[i] += x;
}

int query(int k)
{
    int res = 0;
    for (int i = k; i; i -= lowbit(i))
        res += tr[i];
    return res;
}

void init()
{
    scanf("%d", &n);
    for (int i = 2; i <= n; i++)
        scanf("%d", &a[i]);
    for (int i = 1; i <= n; i++)
        modify(i, 1);
}

void solve()
{
    int p, s, sum;
    int base = log2(n);
    for (int i = n; i; i--)
    {
        p = 0;
        sum = 0;
        for(s = base; s >= 0; s--)
            if(p + (1 << s) <= n && sum + tr[p + (1 << s)] < a[i] + 1)
            {   
                p += 1 << s;
                sum += tr[p];
            }
        h[i] = p + 1;
        modify(h[i], -1);
    }
}

int main()
{
    init();
    solve();
    for (int i = 1; i <= n; i++)
        printf("%d\n", h[i]);
    return 0;
}

 

posted @ 2024-02-28 16:29  Gold_stein  阅读(3)  评论(0编辑  收藏  举报