POJ 2828.Buy Tickets-完全版线段树(单点更新、逆序遍历查询)

POJ2828.Buy Tickets

这个题是插队问题,每次有人插队的时候,其后的所有数据都要进行更新,如果我们反着推,就可以把所有的数据都安排好并且不用再对已插入的数据进行更新,因为逆序处理的话所有的位置都是确定的,第i个人插进来,这个人前面一定有i个空位。逆序遍历一遍查询更新线段树就可以。

这个题简直要写哭了,本来是个基础题,但是我自己的线段树模板的左儿子lson是l,m,右儿子rson是m+1,r,程序直接跑崩了,右儿子改成m,r就可以过,并不是很懂为什么。要了学长的代码,学长写的是我模板那样的,但是我稍微改一下,将update和query合成一个就出问题了,很烦,改代码改了两天,还是不知道为什么,写的我好难过,想哭。难受。

先贴一下rson是m,r的,再贴一下rson是m+1,r的

代码1:

 1 //E
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<cstdlib>
 8 #include<queue>
 9 #include<stack>
10 using namespace std;
11 typedef long long ll;
12 const int inf=0x3f3f3f3f;
13 const double eps=1e-5;
14 const int maxn=5*1e5+10;
15 #define lson l,m,rt<<1
16 #define rson m,r,rt<<1|1
17 struct node{
18     int pos,val;
19 }a[maxn];
20 
21 int tree[maxn<<2],ans[maxn];
22 
23 void build(int l,int r,int rt){
24     tree[rt]=r-l;
25     if(tree[rt]==1)
26         return ;
27 
28     int m=(l+r)>>1;
29     build(lson);
30     build(rson);
31 }
32 
33 void update(int pos,int val,int l,int r,int rt){
34     --tree[rt];
35     if(r-l==1){
36         ans[l]=val;
37         return ;
38     }
39     int m=(l+r)>>1;
40     if(pos<tree[rt<<1]) update(pos,val,lson);
41     else update(pos-tree[rt<<1],val,rson);
42 }
43 
44 int main(){
45     int n;
46     while(~scanf("%d",&n)){
47         for(int i=0;i<n;i++)
48             scanf("%d%d",&a[i].pos,&a[i].val);
49         build(0,n,1);
50         for(int i=n-1;i>=0;i--)
51             update(a[i].pos,a[i].val,0,n,1);
52         for(int i=0;i<n;i++){
53             if(i==0)printf("%d",ans[i]);
54             else printf(" %d",ans[i]);
55         }
56         cout<<endl;
57     }
58     return 0;
59 }

代码2:

 1 //自己手贱改一改试试
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<string>
 7 #include<algorithm>
 8 #include<map>
 9 #include<set>
10 #include<queue>
11 #include<stack>
12 #include<sstream>
13 using namespace std;
14 #define lson l,m,rt<<1
15 #define rson m+1,r,rt<<1|1
16 typedef long long ll;
17 const int maxn=2*1e5+10;
18 const int inf=0x3f3f3f3f;
19 const int mod=998244353;
20 const double eps=1e-5;
21 typedef long long ll;
22 using namespace std;
23 struct node{
24     int pos,val;
25 }a[maxn];
26 int ans[maxn],vis[maxn];
27 int tree[maxn<<2];
28 int p,v;
29 void PushUp(int rt){
30     tree[rt]=tree[rt<<1]+tree[rt<<1|1];
31 }
32 void update(int l,int r,int rt)
33 {
34     int m=l+(r-l)/2;
35     if(l==r)tree[rt]+=v;
36     else
37     {
38         if(p<=m)update(lson);
39         else update(rson);
40         PushUp(rt);
41     }
42 }
43 int query(int pos,int l,int r,int rt)
44 {
45     int m=l+(r-l)/2;
46     if(tree[rt]==pos&&!vis[r])
47         return r;
48     if(tree[rt<<1]>=pos)
49         return query(pos,lson);
50     else
51         return query(pos-tree[rt<<1],rson);
52 }
53 int main()
54 {
55     int n;
56     while(~scanf("%d",&n))
57     {
58         memset(tree,0,sizeof(tree));
59         memset(vis,0,sizeof(vis));
60         for(int i=0;i<n;i++)
61         {
62             v=1;p=i;
63             update(0,n-1,1);
64         }
65         for(int i=0;i<n;i++)
66         {
67             scanf("%d%d",&a[i].pos,&a[i].val);
68         }
69 
70         for(int i=n-1;i>=0;i--)
71         {
72             int ret=query(a[i].pos+1,0,n-1,1);
73             ans[ret]=a[i].val;
74             vis[ret]=1;
75             v=-1;p=ret;
76             update(0,n-1,1);
77         }
78         for(int i=0;i<n;i++)
79             printf("%s%d",i==0?"":" ",ans[i]);
80         printf("
");
81     }
82     return 0;
83 }

这5道线段树的题就先这样吧。

真的是难过,可这就是生活。

原文地址:https://www.cnblogs.com/ZERO-/p/9729097.html