版权声明:本文为博主原创文章,未经博主允许不得转载。 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
要注意判断是否单调之类的