树状数组之较复杂的题(较抽象,需要较强的逻辑思维能力)
程序员文章站
2022-04-06 23:37:42
...
#include <cstdio>
using namespace std;
/*本来我想全部置1,取了的序号置零来着,但是大佬复杂度这么低的算法都快要超时了,我的大概率会超时*/
/*这道题看了好久*/
const int kMax = 500000 + 10;
int n;
int sum[kMax];//下标前有几个人
inline int lowbit(int x) { return x & -x; }
int getsum(int x) {
int res = 0;
for(;x;x -= lowbit(x)) {
res += sum[x];
}
return res;
}
void add(int x) {
for(;x <= n;x += lowbit(x)) {
++ sum[x];
}
}
int num[kMax], res[kMax];
int main() {
int t;
scanf("%d", &n);
for(int i = 1;i < n;++ i)
scanf("%d", &num[i]);
for(int i = n - 1;i >= 0;-- i) {
res[i] = num[i] + 1;//最后一个数
while(true) {
t = num[i] + 1 + getsum(res[i]);//尝试下一个序号
if(res[i] >= t) break;//我觉得不会大于,大于就凉凉了,但是我改成等号的第一次提交评测系统判超时
//后来再提交,都过了
res[i] = t;//
}
add(res[i]);//当前位置加1,表示该序号已用,后面的序号前面人数+1;
}
for(int i = 0;i < n;++ i) {
printf("%d\n", res[i]);
}
return 0;
}