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道线段树的题就先这样吧。
真的是难过,可这就是生活。