其实题目很简单,但是我 w a wa wa了两次,这道题的意思其实就是给出一个序列中每个数前面有多少个数比它大,还原这个序列。
思路:
貌似很难,黑题,严重怀疑恶意品分,这题我们从后往前还原,因为最后一位容易推出来,即在还未用过的数字里找到满足
a
[
i
]
a[i]
a[i]大小关系的即可,如果前面没有比它大的,那该位一定是剩下的数里最大的,如果前面有一个比它大的,那它就是次大的。
数据范围
2
e
5
2e5
2e5,我们可以用树状数组统计数字的使用情况,然后二分答案,每次看答案前面有多少数字没有用过,少了或者多了,就根据情况
转移一下
L
L
L或
R
R
R。
这题也可以用平衡树做,思路感觉更清楚一点,可以看一下
P
O
J
POJ
POJ-
2182
2182
2182
L
o
s
t
Lost
Lost
C
o
w
s
Cows
Cows。
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int n,a[N],c[N],ans[N];
int loubit(int x){
return x&-x;
}
int sum(int i){
int s=0;
while(i>0){
s+=c[i];
i-=loubit(i);
}
return s;
}
void add(int i,int x){
while(i<=n){
c[i]+=x;
i+=loubit(i);
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(c,0,sizeof(c));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=n;i>=1;i--){
int l=1,r=n;
while(r>l){
int mid=(l+r)>>1;
if(i-(mid-sum(mid))<=a[i]){
r=mid;
}else{
l=mid+1;
}
}
ans[i]=l;
add(l,1);
}
for(int i=1;i<=n;i++){
printf("%d ",ans[i]);
}
printf("\n");
}
}
大家可以发现,A了这题的都是我校巨佬
%%%
S
h
u
r
a
E
y
e
ShuraEye
ShuraEye
%%%
20181
20181
20181
g
d
g
z
o
i
gdgzoi
gdgzoi
236
236
236_
l
c
lc
lc
%%%
t
y
l
o
n
tylon
tylon
%%%
t
y
l
o
n
tylon
tylon
2006
2006
2006
%%%
E
v
a
n
Evan
Evan
704
704
704
另外感谢为题目翻译做出贡献的: x y j xyj xyj 1 1 1