AcWing 244. 谜一样的牛

树状数组+二分
sum(x)返回x之前有多少个点已经被取走了,a[i]+1为左边界,n为右边界,判断sum(x)和(x-1-a[i])大小即可
#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e5+10;

int n;
int a[N],tr[N];

int lowbit(int x){
    return x & -x;
}

void add(int x,int c){
    for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}

int sum(int x){
    int res=0;
    for(int i=x;i>=1;i-=lowbit(i)) res+=tr[i];
    return res;
}

int binary_search(int x){
    int l=x,r=n;
    while(l<r){
        int mid=l+r>>1;
        if(sum(mid)<=mid-x) r=mid;
        else l=mid+1;
    }
    return l;
}

int main(){
    cin>>n;
    LL tot=(LL)(1+n)*n/2;
    sizeof(tr,0,sizeof tr);
    for(int i=2;i<=n;i++){
        cin>>a[i];
    }
    vector<int> ans;
    for(int i=n;i>=2;i--){
        int cur=binary_search(a[i]+1);
        tot-=(LL)cur;
        ans.push_back(cur);
        add(cur,1);
    }
    cout<<tot<<endl;
    for(int i=n-2;i>=0;i--) cout<<ans[i]<<endl;
    return 0;
}
posted @ 2022-05-21 16:20  xhy666  阅读(30)  评论(0)    收藏  举报