POJ 2828 Buy Tickets | 线段树的喵用

题意:

给你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 }

 

posted @ 2017-11-20 15:53  MSPqwq  阅读(178)  评论(0编辑  收藏  举报