191113-Lost cows
题目描述
解析
完整题意翻译:已知第i头牛前面有 a i a_i ai头牛比它低,求每头牛的身高(已知每头牛的身高为1~n且互不相同) n < = 1 e 5 n<=1e5 n<=1e5
解析:首先我们倒着来考虑整个奶牛序列,如果第n头牛前面有
a
n
a_n
an头牛比它低,那么它的身高必为
a
n
+
1
a_n+1
an+1,再来考虑第n-1头牛
1,如果
a
n
−
1
<
a
n
a_{n-1}<a_n
an−1<an,即第n-1头牛比第n头牛低,那么它的身高必为
a
n
−
1
+
1
a_{n-1}+1
an−1+1,
2,否则,他的身高为
a
n
−
1
+
2
a_{n-1}+2
an−1+2
后面的牛以此类推
那么其实题意可以简化为,维护一个01序列,倒序扫描每头牛,每次进行两次操作,假设当前扫描到第i头牛
1,在整个01序列中找第
a
i
+
1
a_i+1
ai+1个1的位置,该位置号即为第i头牛的身高
2,将原序列该位置变为0
那么我们考虑如何维护这个01序列?
1,树状数组+二分,单次操作:
O
(
l
o
g
2
n
)
O(log^2n)
O(log2n)
树状数组维护前缀1的个数,每次查找时,二分这个位置,最后再单点修改即可
2,树状数组+倍增 单次操作:
O
(
l
o
g
n
)
O(logn)
O(logn)
不会,先咕掉
题解
1,树状数组+二分
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#define M 100009
using namespace std;
int a[M],h[M],tree[M],n;
int read(){
int f=1,re=0;
char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-'){
f=-1;
ch=getchar();
}
for(;isdigit(ch);ch=getchar())
re=(re<<3)+(re<<1)+ch-'0';
return re*f;
}
int lowbit(int i){
return i&(-i);
}
void update(int x,int y){
while(x<=n){
tree[x]+=y;
x+=lowbit(x);
}
}
int query(int x){
int sum=0;
while(x>0){
sum+=tree[x];
x-=lowbit(x);
}
return sum;
}
int main(){
n=read();
for(int i=2;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) update(i,1);
for(int i=n;i>=1;i--){
int l=1,r=n;
while(l<r){
int mid=(l+r)>>1;
if(query(mid)>a[i]) r=mid;
else l=mid+1;
}
h[i]=r;
update(r,-1);
}
for(int i=1;i<=n;i++)
printf("%d\n",h[i]);
return 0;
}