Problem Q
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 35 Accepted Submission(s) : 23
Regrettably, FJ does not have a way to sort them. Furthermore, he's not very good at observing problems. Instead of writing down each cow's brand, he determined a rather silly statistic: For each cow in line, he knows the number of cows that precede that cow in line that do, in fact, have smaller brands than that cow.
Given this data, tell FJ the exact ordering of the cows.
5 1 2 1 0
2 4 5 3 1
树状数组。初始时,树状数组为全0.sum(x)表示已经确定了值的且小于等于x的值的个数。
我们依然从后往前倒推,对于当前考虑的a[n],假设它的值为x,那么我们就执行add(x,1)。接下来我们要找到a[n-1]的值y,y肯定在[1,8000]范围内,所以可以用二分查找确定y的值。如果我们猜y=8的话,如果a[n-1]=4并且比8小的已经确定了的值即sum(7)=3,可以说明从1到7中:由有3个数的值已经确定了 并且 还有4个值没有确定且这些没确定值的比y小的数正好是4个,那么y肯定>=8。可以加大y的范围继续探测。如果sum(7)+4<7的话,8就比y本来的值要大了。
如果sum(7)+4>7的话,8就比y本来的值要小。
由此可得一般结论,我们猜测当前a[i]的值为y,如果
Sum(y-1)+a[i]==y-1 那么y为最小值
Sum(y-1)+a[i]<y-1 那么y-1为最大值
Sum(y-1)+a[i]>y-1 那么y+1为最小值
AC代码:0ms 注意if else语句的顺序,发生概率大的语句放前面。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN =8008;
int a[MAXN];
int ans[MAXN];
int c[MAXN];
int n;
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int res=0;
while(x)
{
res +=c[x];
x-=lowbit(x);
}
return res;
}
void add(int x,int v)
{
while(x<=n)
{
c[x]+=v;
x+=lowbit(x);
}
}
int main()
{
ios::sync_with_stdio(false);
while(cin>>n&&n)
{
a[1]=0;
memset(c,0,sizeof(c));
for(int i=2;i<=n;i++)
cin>>a[i];
ans[n] = a[n]+1;
add(a[n] + 1 , 1);
for(int i=n-1;i>=1;i--)
{
int L=1,R=n;
while(R>L)
{
int mid = (R+L+1)/2;
if(sum(mid-1)+a[i] < mid-1)
R=mid-1;
else if(sum(mid-1)+a[i] == mid-1)
L=mid;
else
L=mid+1;
}
ans[i]= L ;
add(ans[i] , 1 );
}
for(int i=1;i<=n;i++)
cout<<ans[i]<<endl;
}
return 0;
}