pojBuy Tickets2828线段树或者树状数组(队列中倒序插队)


这题开始的思路就是模拟:就像数组中插点一样,每一个想买票的人都想往前插队!
但是这样的话肯定TLE, 看了别人的思路之后才恍然大悟!
正解:
    将开始的正序插入,变成倒序插入,这样的话,想一想:第 i 个人想要插在 p[i]
    的位置上,那么就要保证所插入的位置之前一定要有 p[i]-1个空位!因为一定会有p[j]<p[i]
    (0<=p[j]<=j,每个人都想往前插队) 
    的第j个人插在p[i]的位置的前边! 
    
    如果i<j; && p[i]==p[j], 倒序插入中,第j个人先插入, 那么第i个人在保证插入的位置之前有
    p[i]-1个空位的同时,又要插入到第 j 个人的后边! 




1
#include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #define M 200005 6 using namespace std; 7 8 pair<int, int>per[M]; 9 int ret[M]; 10 int tree[M*4]; 11 int n; 12 13 void buildT(int p, int ld, int rd){ 14 if(ld==rd){ 15 tree[p]=1; 16 return ; 17 } 18 int mid=(ld+rd)>>1; 19 buildT(p<<1, ld, mid); 20 buildT(p<<1|1, mid+1, rd); 21 tree[p]=tree[p<<1]+tree[p<<1|1]; 22 } 23 24 void updateT(int p, int ld, int rd, int pos, int val){ 25 if(ld==rd){ 26 tree[p]=0; 27 ret[ld]=val; 28 return ; 29 } 30 int mid=(ld+rd)>>1; 31 if(tree[p<<1]>pos) 32 updateT(p<<1, ld, mid, pos, val); 33 else 34 updateT(p<<1|1, mid+1, rd, pos-tree[p<<1], val); 35 36 tree[p]=tree[p<<1]+tree[p<<1|1]; 37 } 38 39 int main(){ 40 int i; 41 while(scanf("%d", &n)!=EOF){ 42 buildT(1, 1, n); 43 for(i=1; i<=n; ++i) 44 scanf("%d%d", &per[i].first, &per[i].second); 45 for(i=n; i>=1; --i) 46 updateT(1, 1, n, per[i].first, per[i].second); 47 48 printf("%d", ret[1]); 49 for(i=2; i<=n; ++i) 50 printf(" %d", ret[i]); 51 printf(" "); 52 } 53 return 0; 54 }
 1 //树状数组~~不解释
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<algorithm>
 6 
 7 #define N 200005
 8 using namespace std;
 9 
10 int tree[N];
11 int pos[N], val[N];
12 int ret[N];
13 int n;
14 
15 int lowbit(int x){
16     return x&(-x);
17 }
18 
19 void buildT(){
20     for(int i=1; i<=n; ++i){
21         tree[i]=0;
22         for(int j=i-lowbit(i)+1; j<=i; ++j)
23             tree[i]+=1;
24     }
25 }
26 
27 void updateT(int x){
28     while(x<=n){
29         tree[x]-=1;
30         x+=lowbit(x);
31     }
32 }
33 
34 int getSum(int x){
35     int s=0;
36     while(x>0){
37         s+=tree[x];
38         x-=lowbit(x);    
39     }
40     return s;
41 }
42 
43 int main(){
44     while(scanf("%d", &n)!=EOF){
45         buildT(); 
46         for(int i=1; i<=n; ++i){
47             scanf("%d%d", &pos[i], &val[i]);
48             ret[i]=-1;
49         }
50         for(int i=n; i>=1; --i){
51             int ld=1, rd=n;
52             bool flag=false;
53             while(ld<=rd){
54                 int mid=(ld+rd)>>1;
55                 int s=getSum(mid);
56                 //如果当前的位置没有人插入并且该位置的之前的人数恰好为pos[i] 
57                 if(ret[mid]==-1 && s==pos[i]+1){ 
58                     updateT(mid);
59                     ret[mid]=val[i];
60                     flag=true;//已经找到不用在继续寻找了 
61                     break;
62                 }
63                 else if(s>=pos[i]+1)
64                     rd=mid-1;
65                 else ld=mid+1;
66             }
67             if(!flag) ret[rd+1]=val[i];//直到找到当前的位置没有人插入并且该位置的之前的人数恰好为pos[i]  
68         }
69         printf("%d", ret[1]);
70         for(int i=2; i<=n; ++i)
71              printf(" %d", ret[i]);
72         printf("
"); 
73     } 
74     return 0; 
75 }
原文地址:https://www.cnblogs.com/hujunzheng/p/3885134.html