九度OJ 1344:可乐瓶展览 (DP)

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:430

解决:76

题目描述:
众所周知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;
}


原文地址:https://www.cnblogs.com/liangrx06/p/5083789.html