https://codeforces.com/contest/1208/problem/D
思路:开始是想二分找位置尝试往连续的(1+x)*x/2去做,发现没有规律。
考虑从 1 -> n 去构造答案,试想对于1来说,肯定是最后一个0的位置,然后我们可以让0后面的所有数字就减去1,这样继续找0最后的位置即可。
删除当前的数(赋值为无穷大)
然后对于找到的位置后面所有元素减少 i 。
不断找最小值的位置
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+1000;
typedef long long LL;
const LL inf=1e18;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL ans[maxn];
struct Tree{
LL l,r,minval,tag;
}tree[maxn*4];
void push_up(LL p){
tree[p].minval=min(tree[p*2].minval,tree[p*2+1].minval);
}
void addtag(LL p,LL d){
tree[p].tag+=d;
tree[p].minval+=d;
}
void push_down(LL p){
if(tree[p].tag!=0){
addtag(p*2,tree[p].tag);
addtag(p*2+1,tree[p].tag);
tree[p].tag=0;
}
}
void build(LL p,LL l,LL r){
tree[p].l=l;tree[p].r=r;tree[p].tag=0;tree[p].minval=inf;
if(l==r){cin>>tree[p].minval;return;}
LL mid=(l+r)>>1;
build(p*2,l,mid);build(p*2+1,mid+1,r);
push_up(p);
}
void modify(LL p,LL l,LL r,LL d){
if(l<=tree[p].l&&r>=tree[p].r){
addtag(p,d);
return;
}
push_down(p);
LL mid=(tree[p].l+tree[p].r)>>1;
if(l<=mid) modify(p*2,l,r,d);
if(r>mid) modify(p*2+1,l,r,d);
push_up(p);
}
LL query(LL p,LL l,LL r){
if(tree[p].l==tree[p].r){
return tree[p].l;
}
push_down(p);
LL mid=(tree[p].l+tree[p].r)>>1;
if(tree[p*2].minval<tree[p*2+1].minval){
return query(p*2,l,r);
}
else return query(p*2+1,l,r);
}
int main(void){
cin.tie(0);std::ios::sync_with_stdio(false);
LL n;cin>>n;
build(1,1,n);
for(LL i=1;i<=n;i++){
LL pos=query(1,1,n);///返回最小值的位置
ans[pos]=i;
modify(1,pos,pos,inf);
modify(1,pos+1,n,-i);
}
for(LL i=1;i<=n;i++) cout<<ans[i]<<" ";
cout<<"\n";
return 0;
}