POJ--2182剩余第K大(暴力/树状数组+二分)

Posted liyexin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ--2182剩余第K大(暴力/树状数组+二分)相关的知识,希望对你有一定的参考价值。

地址:http://poj.org/problem?id=2182

题意:

N头奶牛排队,它们的身高为1~n,已知每头牛前面有多少头比自己矮,求每头牛的身高。

解析:

输入其实是从i=2开始的

暴力代码:跑了438M

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=8005;
int vis[maxn];
int p[maxn];
int a[maxn];
int main()
{
    int n;
    cin>>n;
    for(int i=2;i<=n;i++)
        cin>>p[i];
    p[1]=0;
    int tot=1;
    for(int i=n;i>=1;i--)
    {
        int ans=0;
        int md=p[i]+1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j])
            {
                ans++;
                if(ans==md)
                {
                    a[tot++]=j;
                    vis[j]=1;
                    break;
                }
            }
        }
    }
    for(int i=n;i>=1;i--)
    {
            cout<<a[i]<<endl;
    }
}

树状数组做法:

树状数组优化暴力代码的第二层for:剩余未被标记的数目

通过树状数组来维护一个0/1序列,c[i],表示小于等于 i 而且未被使用的数有几个。

add(1,1),add(2,1).....add(n,1)这样就维护了一个初始序列:

数:      1,2,3,4,5

它前面比它小的:1,2,3,4,5

从后往前看a[i],那么一个位置的数,就是未被使用的数中第a[i]+1大个

所以通过二分find(a[i]+1),找到一个数md,满足<=md且未被使用的数有a[i]+1个,输出它,

而且:update(md,-1),这个数被使用,那么后面自然都要-1

代码:47ms,比暴力快得不是一点~

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=8e3+10;
int c[maxn],a[maxn],b[maxn];
int n;
int lowbit(int x)
{
    return x&(-x);
}
void update(int id,int x)
{
    for(int i=id;i<maxn;i+=lowbit(i))
        c[i]+=x;
}
int getsum(int id)
{
    int sum=0;
    for(int i=id;i>0;i-=lowbit(i))
        sum+=c[i];
    return sum;
}
int find(int x)
{
    int l=1,r=n;
    int ok;
    while(l<r)
    {
        int md=(l+r)>>1;
        if(getsum(md)>=x)
        {
            r=md;
        }
        else
            l=md+1;
    }
    return r;
}
int main()
{

    scanf("%d",&n);
    update(1,1);
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&a[i]);
        update(i,1);
    }
    int tot = 1;
    for(int i=n;i>=1;i--)
    {
        int md=find(a[i]+1);
        b[i]=md;
        update(md,-1);
    }
    for(int i=1;i<=n;i++)
        cout<<b[i]<<endl;
}

 

以上是关于POJ--2182剩余第K大(暴力/树状数组+二分)的主要内容,如果未能解决你的问题,请参考以下文章

POJ2182 Lost Cows (树状数组+二分)

POJ 2182 Lost Cows

poj2182Lost Cows——树状数组快速查找

POJ2182 Lost Cows 树状数组,二分

POJ2182:Lost Cows

POJ 2182 Lost Cows (树状数组 && 二分查找)