题目链接:http://codeforces.com/contest/474/problem/F
意思是给你两个数n和d,下面给你n座山的高度。
一个人任意选择一座山作为起始点,向右跳,但是只能跳到高度差的绝对值大于等于d的山上。
问跳过的最长路径是什么。
设dp[h[i]]是跳到第i座山的最长路径长度。
那么dp[h[i]] = max( dp[h[j]] ) + 1 ( |h[i]-h[j]| >=d && i>j )
因为要查询区间最大值,所以考虑用线段树实现。
从左向右扫,线段树seg[i]维护的是走到高度为i的山走的最长路径
那么先找出 区间 [0,h[i]-d] 的最长路径,再找出区间 [h[i]+d,n]的最长路径
然后求出最大的加1,再放入线段树的h[i]位置中。
注意要维护路径 还有离散化
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 5 const int MAX_N = 3*1e5+100; 6 LL h[MAX_N],b[MAX_N]; 7 // 这里写的时候偷懒了,sum代表高度对应的最长路径,maxn代表当前高度对应的最近的下标 8 int sum[MAX_N<<2], maxn[MAX_N<<2],dp[MAX_N],qq[MAX_N],n,d; 9 int route[MAX_N]; 10 11 void push_up(int idx){ 12 sum[idx] = max(sum[idx<<1],sum[idx<<1|1]); 13 if( sum[idx<<1]>sum[idx<<1|1] ) maxn[idx] = maxn[idx<<1]; 14 else maxn[idx] = maxn[idx<<1|1]; 15 } 16 17 // 更新pos的山的路径长,并且下标置为i 18 void update(int pos,int x,int i,int idx,int l,int r){ 19 if( l==r ){ 20 sum[idx] = x; 21 maxn[idx] = i; 22 return; 23 } 24 int m = l+r>>1; 25 if( pos<=m ) update(pos,x,i,idx<<1,l,m); 26 else update(pos,x,i,idx<<1|1,m+1,r); 27 push_up(idx); 28 } 29 30 // 传入的i是要被修改的,返回路径最长的山的位置 31 int query(int L,int R,int &i,int idx,int l,int r){ 32 if( R<l||r<L ) { 33 i = -1; 34 return -1; 35 } 36 if( L<=l&&R>=r ) { 37 i = maxn[idx]; 38 return sum[idx]; 39 } 40 int m = l+r>>1 , res = -1; 41 if( L<=m ) { 42 int s; 43 int Q = query(L,R,s,idx<<1,l,m); 44 if( Q>res ){ 45 i = s; 46 res = Q; 47 } 48 } 49 if( R>m ){ 50 int s; 51 int Q = query(L,R,s,idx<<1|1,m+1,r); 52 if( Q>res ) { 53 res = Q; 54 i = s; 55 } 56 } 57 return res; 58 } 59 60 int main(){ 61 memset(maxn,-1,sizeof(maxn)); 62 63 int ptr = 0; 64 scanf("%d%d",&n,&d); 65 for(int i=0;i<n;i++){ 66 scanf("%I64d",&h[i]); 67 b[ptr++] = h[i]; 68 b[ptr++] = h[i]-1LL*d; 69 b[ptr++] = h[i]+1LL*d; 70 } 71 sort(b,b+ptr); 72 int ub = unique(b,b+ptr) - b; 73 74 for(int i=0;i<n;i++){ 75 int r = lower_bound(b,b+ub,h[i]+d) - b; 76 int lmax = -1; 77 int rs = query(r,ptr-1,lmax,1,0,ptr-1); 78 int rmax = -1; 79 int l = lower_bound(b,b+ub,h[i]-d) - b; 80 int ls = query(0,l,rmax,1,0,ptr-1); 81 qq[i] = max(ls,rs); 82 int t = lower_bound(b,b+ub,h[i]) - b; 83 update(t,qq[i]+1,i,1,0,ptr-1); 84 if(ls>rs){ 85 dp[i] = rmax; 86 } else { 87 dp[i] = lmax; 88 } 89 } 90 int idx = maxn[1]; 91 int ED = sum[1]; 92 printf("%d\n",ED); 93 int ptrr = 0; 94 route[ptrr++] = idx; 95 while( route[ptrr-1]>0 ){ 96 int s = route[ptrr-1]; 97 route[ptrr] = dp[s]; 98 ptrr++; 99 } 100 while( route[ptrr-1]<0 ) ptrr--; 101 for(int i=ptrr-1;i>=0;i--){ 102 printf("%d ",route[i]+1); 103 } 104 return 0; 105 }
浙公网安备 33010602011771号