poj2182 Lost Cow

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zz_ylolita/article/details/51982307

根据题目给出的数列的性质,每次可以求出最后一头牛的编号

也就是在当前有的数列1  2  3 ....   n 中找到第a[i]+1小的数

可以用树状数组或者线段树,记录的是已经删除了的数的个数

还有的数的个数为     区间长度-区间记录的数字

这个是单调的(不严格),所以可以用二分查找优化

然后更新一下就可以了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int n,k,a[8010],c[8010];
int lowbit(int x)
{
    return x & (-x);
}
void updata(int x)
{
    while (x<=n)
    {
        c[x]+=1;
        x+=lowbit(x);
    }
}
int ask(int x)
{
    int s=0;//一定要初始化为0
    while (x>0)
    {
        s+=c[x];
        x-=lowbit(x);
    }
    return s;
}
int find(int x)
{
    int l=1,r=n,mid,num;
    while (l<r)
    {
        mid=(l + r) >> 1;//!!
        num=ask(mid);
        if (mid-num < x) l=mid+1; else r=mid;
    }
    return l;
}
int main()
{
    scanf("%d", &n);
    for (int i=2;i<=n;i++) scanf("%d", &a[i]);
    for (int i=n;i>=1;i--)
    {
        k=find(a[i]+1);
        a[i]=k;
        updata(k);
    }
    for (int i=1;i<=n;i++) printf("%d\n", a[i]);
}


两个月没碰,果然生疏很多

要注意在过程里定义变量一定要初始化为0或者什么的

二分法的mid=(l + r ) >> 1

while 的条件是(l<r)

返回的是l

要注意判断是否单调之类的



猜你喜欢

转载自blog.csdn.net/zz_ylolita/article/details/51982307