https://codeforc.es/contest/1208/problem/D
线段树维护从1到n的前缀和,从后往前查询第一个前缀和大于ai的位置,线段树简单操作我竟然没当场写出来555
1 #define bug(x) cout<<#x<<" is "<<x<<endl 2 #define IO std::ios::sync_with_stdio(0) 3 #include <bits/stdc++.h> 4 #define iter ::iterator 5 #define pa pair<int,ll> 6 using namespace std; 7 #define ll long long 8 #define mk make_pair 9 #define pb push_back 10 #define se second 11 #define fi first 12 #define ls o<<1 13 #define rs o<<1|1 14 ll mod=998244353; 15 const int N=2e5+5; 16 ll a[N]; 17 ll mx[N*4],lz[N*4]; 18 void down(int o){ 19 if(lz[o]){ 20 mx[ls]+=lz[o]; 21 mx[rs]+=lz[o]; 22 lz[ls]+=lz[o]; 23 lz[rs]+=lz[o]; 24 lz[o]=0; 25 } 26 } 27 void up(int o,int l,int r,int ql,int qr,ll v){ 28 if(l>=ql&&r<=qr){ 29 mx[o]+=v; 30 lz[o]+=v; 31 return; 32 } 33 int m=(l+r)/2; 34 down(o); 35 if(ql<=m)up(ls,l,m,ql,qr,v); 36 if(qr>m)up(rs,m+1,r,ql,qr,v); 37 mx[o]=max(mx[ls],mx[rs]); 38 } 39 int qu(int o,int l,int r,ll v){ 40 //printf("l=%d r=%d sum=%d ",l,r,sum[o]); 41 if(l==r)return l; 42 int m=(l+r)/2; 43 down(o); 44 if(v>=mx[ls])return qu(rs,m+1,r,v); 45 return qu(ls,l,m,v); 46 mx[o]=max(mx[ls],mx[rs]); 47 } 48 int n; 49 int b[N]; 50 int main(){ 51 IO; 52 cin>>n; 53 for(int i=1;i<=n;i++){ 54 cin>>a[i]; 55 } 56 ll h=0; 57 for(int i=1;i<=n;i++){ 58 h+=i; 59 up(1,1,n,i,i,h); 60 } 61 for(int i=n;i>=1;i--){ 62 ll x=a[i]; 63 int res=qu(1,1,n,x); 64 b[i]=res; 65 up(1,1,n,b[i],n,-b[i]); 66 } 67 for(int i=1;i<=n;i++){ 68 cout<<b[i]<<" "; 69 } 70 } 71 /* 72 5 73 0 1 1 1 10 74 */