这题很容易想到O(n^2)的做法,但这样肯定是要超时的,对于第i个box,可以用线段树在logn的时间内找出小于mes[i].h且能拿到最多金子的box。
类型:线段树优化Dp。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 #define lson l,m,rt<<1 5 #define rson m+1,r,rt<<1|1 6 #define maxn 100005 7 struct { 8 int max; 9 }setree[maxn<<2]; 10 struct op{ 11 int h,val; 12 }mes[maxn]; 13 int num[maxn]; 14 void build(int l,int r,int rt) 15 { 16 setree[rt].max=0; 17 if(l==r) 18 return; 19 int m=(l+r)>>1; 20 build(lson); 21 build(rson); 22 } 23 int binsearch(int l,int r,int c) 24 { 25 int m=(l+r)>>1; 26 if(num[m]==c) 27 return m; 28 if(c<num[m]) 29 return binsearch(l,m-1,c); 30 else 31 return binsearch(m+1,r,c); 32 } 33 void pushup(int rt) 34 { 35 setree[rt].max=max(setree[rt<<1].max,setree[rt<<1|1].max); 36 } 37 void update(int l,int r,int rt,int num,int c) 38 { 39 if(l==r){ 40 setree[rt].max=max(setree[rt].max,c); 41 return; 42 } 43 int m=(l+r)>>1; 44 if(num<=m) 45 update(lson,num,c); 46 else 47 update(rson,num,c); 48 pushup(rt); 49 } 50 int query(int l,int r,int rt,int L,int R) 51 { 52 if(L>R) 53 return 0; 54 if(L<=l&&r<=R) 55 return setree[rt].max; 56 int m=(l+r)>>1; 57 int ans=0; 58 if(L<=m) 59 ans=max(ans,query(lson,L,R)); 60 if(R>m) 61 ans=max(ans,query(rson,L,R)); 62 return ans; 63 } 64 int main() 65 { 66 int n; 67 while(~scanf("%d",&n)){ 68 for(int i=1;i<=n;i++){ 69 scanf("%d%d",&mes[i].h,&mes[i].val); 70 num[i]=mes[i].h; 71 } 72 sort(num+1,num+n+1); 73 int k=1; 74 for(int i=2;i<=n;i++) 75 if(num[i]!=num[i-1]) 76 num[++k]=num[i]; 77 build(1,k,1); 78 int ans=0; 79 for(int i=1;i<=n;i++){ 80 int num=binsearch(1,k,mes[i].h); 81 int ret=query(1,k,1,1,num-1)+mes[i].val; 82 ans=max(ans,ret); 83 update(1,k,1,num,ret); 84 } 85 printf("%d\n",ans); 86 } 87 return 0; 88 }