九度OJ 1344:可乐瓶展览 (DP)
- 题目描述:
-
众所周知JOBDU旗下的JOBCOLA公司是文明全球的著名可乐制造商,与其它可乐公司不同的是,JOBCOLA可乐公司并不是以其可乐的味道闻名,而是以其不同寻常的包装瓶被消费者所津津乐道。在JOBCOLA可乐公司成立100周年的日子里,公司搜集了历年来生产的可乐瓶,想通过举办一个可乐瓶展览,以此来提高公司的文化品位。但是受制于展览场地的大小,只能展出一部分的瓶子。经过JOBDU董事会与展览承办商协商之后,决定选出一个连续时期的瓶子用于展览,同时为了达到最佳的美学感受,在所展览的瓶子中,最高的瓶子和最低的瓶子之间的高度,不能超过k。给你的任务就是,挑选出满足上述要求的最长瓶子序列,供董事会选择。
- 输入:
-
每个测试案例包括两行:第一行为两个整数,n和k,其中n代表待选的瓶子个数,k为所选出的瓶子中最高瓶子和最低瓶子之间的最大落差。其中1 <= n <= 105, 0 <= k <= 106。第二行包含n个整数,每个整数代表瓶子的高度(单位为微米),已知所有瓶子都已经按照生产年代,从古到今进行了排序。
- 输出:
- 对应每个测试案例,输出的第一行包括两个整数a, b。其中a代表满足条件的瓶子个数;b则代表有多少组这样的选择方案。接下来再输出b行,每行包括两个整数s, e (1 <=s,e <=n),其中s代表所选的a个瓶子中最古老的瓶子的下标,而e则代表该方案中最近生产的瓶子下标。注意:若有多个方案,则按照s从小到大的顺序输出;若s相同,则按照e的大小输出。
- 样例输入:
-
3 2 13 12 10
- 样例输出:
-
2 2 1 2 2 3
思路:
其实我没AC,思路还是有问题。以后找时间再AC。先贴别人的代码。
代码:
//ac code #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; int height[100009]; int n, k; int h[100009][20]; int l[100009][20]; int exp2(unsigned x); int getmax(int x, int y); int getmin(int x, int y); int Ok(int len); int rx[100000]; int ry[100000]; int main(){ while(cin>>n>>k){ for(int i= 0; i< n; ++i){ scanf("%d", height+i); } for(int i= 0; i< n; ++i){ h[i][0]= i; l[i][0]= i; } int x= exp2(n); //RMQ for(int j= 1; j<= x; ++j){ for(int i= 0; i<= n-(1<<j); ++i){ h[i][j]= h[i][j-1]; l[i][j]= l[i][j-1]; if(height[h[i][j]]< height[h[i+(1<<(j-1))][j-1]]){ h[i][j]= h[i+(1<<(j-1))][j-1]; } if(height[l[i][j]]>= height[l[i+(1<<(j-1))][j-1]]){ l[i][j]= l[i+(1<<(j-1))][j-1]; } } } int low= 1, high= n; int mid; //binary search最大值 while(low< high){ mid= (low+high)>>1; if(Ok(mid)){ low= mid+1; }else{ high= mid-1; } } while(!Ok(low)) --low; int a, b; int count= 0; for(int i= 0; i<= n-low; ++i){ a= getmax(i, i+low-1); b= getmin(i, i+low-1); if((height[a]-height[b])<= k){ rx[count]=i; ry[count]=i+low-1; ++count; } } cout<<low<<' '<<count<<endl; for(int i= 0; i< count; ++i){ cout<<rx[i]+1<<' '<<ry[i]+1<<endl; } } } int exp2(unsigned x){ int re= 0; while(x){ x>>=1; ++re; } return re-1; } int getmax(int x, int y){ int p= exp2(y-x+1); if(height[h[x][p]]>= height[h[y-(1<<p)+1][p]]){ return h[x][p]; }else{ return h[y-(1<<p)+1][p]; } } int getmin(int x, int y){ int p= exp2(y-x+1); if(height[l[x][p]]< height[l[y-(1<<p)+1][p]]){ return l[x][p]; }else{ return l[y-(1<<p)+1][p]; } } int Ok(int len){ for(int i= 0; i<= n-len; ++i){ if(height[getmax(i,i+len-1)]-height[getmin(i,i+len-1)]<= k){ return true; } } return false; }
编程算法爱好者。