题意:
给你n次插队操作,每次两个数,pos,w,意为在pos后插入一个权值为w的数;
最后输出1~n的权值
题解:
首先可以发现,最后一次插入的位置是准确的位置
所以这个就变成了若干个子问题,
所以用线段树维护一下每个区间剩余多少位置可选
对于一个pos
如果左儿子的剩余超过当前位置,就递归进左子树
反之就相当于留出了左儿子剩余的位置,递归进右子树,当前位置变成pos-左儿子剩余位置
请注意是在后面插入
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 typedef long long ll; 5 #define N 200010 6 using namespace std; 7 struct node 8 { 9 ll l,r,sum,w; 10 }t[4*N]; 11 ll p[N],w[N]; 12 ll read() 13 { 14 ll ret=0,neg=1; 15 char j=getchar(); 16 for (;j>‘9‘ || j<‘0‘;j=getchar()) 17 if (j==‘-‘) neg=-1; 18 for (;j<=‘9‘ && j>=‘0‘;j=getchar()) 19 ret=ret*10+j-‘0‘; 20 return ret*neg; 21 } 22 ll n,q,l,r,k,ans[N]; 23 void pushup(ll p) 24 { 25 t[p].sum=t[2*p].sum+t[2*p+1].sum; 26 } 27 void build(ll p,ll l,ll r) 28 { 29 t[p].l=l,t[p].r=r; 30 if (l!=r) 31 { 32 ll mid=l+r>>1; 33 build(2*p,l,mid); 34 build(2*p+1,mid+1,r); 35 pushup(p); 36 } 37 else 38 t[p].sum=1; 39 } 40 void modify(ll p,ll pos,ll k) 41 { 42 if (t[p].l==t[p].r) 43 { 44 ans[t[p].l]=k; 45 t[p].sum--; 46 return ; 47 } 48 if (t[2*p].sum>=pos) modify(2*p,pos,k); 49 else modify(2*p+1,pos-t[2*p].sum,k); 50 pushup(p); 51 } 52 int main() 53 { 54 while (scanf("%lld",&n)!=EOF) 55 { 56 build(1,1,n); 57 for (int i=1;i<=n;i++) 58 p[i]=read(),w[i]=read(); 59 for (int i=n;i>=1;i--) 60 modify(1,p[i]+1,w[i]); 61 for (int i=1;i<=n;i++) 62 printf("%lld%c",ans[i]," \n"[i==n]); 63 } 64 return 0; 65 }
时间: 2024-10-09 09:27:50