首页 > 编程语言 > 详细

POJ 2182【树状数组】

时间:2015-11-13 20:51:00      阅读:334      评论:0      收藏:0      [点我收藏+]

题意:

每头牛有编号,他们乱序排成一排,每头牛只知道前边比自己序号小的有几位。

思路:

递推,最后一只牛的编号是确定的,然后不断进行区间更新,直到找到某个空位前方恰好有n个空位。

这题跟某道排队的题思路是一样的,可以线段树,认为树状数组的解法在时间复杂度上比线段树多了一个logN

因为树状数组只能在logn的复杂度内求解出前n个数字的某些特征,所以需要进行二分不断尝试,直到找到某一个位置前方正好有多少个空位,也就是在二分的过程中使得时间复杂度比线段树要高。线段树直接进行查找就好了,复杂度是logn。

反思:

这道题的WA在二分上,并不是前n个空位中恰好有k个空位就可以安置这头牛,因为有可能这个位置本身就已经有人占据了。所以二分一定要使得两个区间端点会和。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int tree[8005];
int tmp[8005];
int ans[8005];
int n;
int lowbit(int a)
{
    return a&(-a);
}
int solve(int tar)
{
    int sum=0;
    while(tar>0)
    {
        sum+=tree[tar];
        tar-=lowbit(tar);
    }
    return sum;
}
int findpos(int tar)
{
    int l=1,r=n;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(solve(mid)<tar)
        {
            l=mid+1;
        }
        else
        {
            r=mid;
        }
    }
    return l;
}
void change(int tar)
{
    while(tar<=n)
    {
        tree[tar]--;
        tar+=lowbit(tar);
    }
}
int main()
{
    scanf("%d",&n);
    tmp[1]=0;
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&tmp[i]);
    }
    for(int i=1;i<=n;i++)
    {
        tree[i]=lowbit(i);
    }
    for(int i=n;i>0;i--)
    {
        int tans=findpos(tmp[i]+1);
        change(tans);
        ans[i]=tans;
    }
    for(int i=1;i<=n;i++)
    {
        printf("%d\n",ans[i]);
    }
    return 0;
}

 

POJ 2182【树状数组】

原文:http://www.cnblogs.com/tun117/p/4963142.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!