題意:

給n數字,以及長度k的框框,問說框框從最左邊移動到最右邊時,中間框住的數字中最大與最小的是誰

 

解法:

可以利用單調性,把框框內的東西由大到小排列,之後每次要加入時,就從後面往前看,若目前看到的人比較小就丟掉,直到看到比他大的人為止,並且塞在他後面

要丟掉時,就從前面往後看,把比目前要丟掉的人的ID還要小的都丟掉,直到第一個ID比要丟掉的還大為止

這樣就2對每個人都只會做到進來與出去兩次,所以是O(n)

不過POJ這題他測資卡很緊(應該是想擋O(nlogn)的解法),所以要做IO優化

 

程式碼:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int num[1000100];
int q  [1000100];
int th [1000100];
int n,k;
int h,t;
char out[123];
int oNum;
int i,j;
unsigned int tmp;
int flag;
void max(){

    h = 1;
    t = 0;
    for(i=1;i<k;++i){
        while(h <=t && q[t]<num[i])--t;
        q[++t]=num[i];
        th[t]=i;
    }
    for(i=k,j=0;i<=n;++i,++j){
        while(h <=t && q[t]<num[i])--t;
        q[++t]=num[i];
        th[t]=i;
        while(th[h]<=j) ++h;

        if(q[h]==0){
            putchar('0');
        }else {
            if(q[h]>0){
                flag = 0;
                tmp = q[h];
            }else {
                flag = 1;
                tmp = -q[h];
            }
            for(oNum=0;tmp>0;tmp/=10,++oNum)out[oNum]=tmp%10+'0';
            if(flag)putchar('-');
            for(--oNum;oNum>=0;--oNum)putchar(out[oNum]);
        }
        putchar((i==n)?'\n':' ');
    }
}
void min(){
    h = 1;
    t = 0;
    for(i=1;i<k;++i){
        while(h <=t && q[t]>num[i])--t;
        q[++t]=num[i];
        th[t]=i;
    }
    for(i=k,j=0;i<=n;++i,++j){
        while(h <=t && q[t]>num[i])--t;
        q[++t]=num[i];
        th[t]=i;
        while(th[h]<=j) ++h;

        if(q[h]==0){
            putchar('0');
        }else {
            if(q[h]>0){
                flag = 0;
                tmp = q[h];
            }else {
                flag = 1;
                tmp = -q[h];
            }
            for(oNum=0;tmp>0;tmp/=10,++oNum)out[oNum]=tmp%10+'0';
            if(flag)putchar('-');
            for(--oNum;oNum>=0;--oNum)putchar(out[oNum]);
        }
        putchar((i==n)?'\n':' ');
    }
}

int main(){
    int i;
    int flag = 0;
    char ch;
    unsigned int tmp;
    while(scanf("%d %d",&n,&k)!=EOF){
        getchar();
        for(i=1;i<=n;++i){
            tmp = 0;
            flag = 0;
            ch=getchar();
            if(ch=='-')flag = 1;
            else tmp = ch-'0';
            while((ch=getchar())){
                if(!(ch>='0'&&ch<='9'))break;
                tmp = tmp*10+ch-'0';
            }
            if(flag)num[i] = -tmp;
            else num[i] = tmp;
        }
        min();
        max();
    }

    return 0;
}

arrow
arrow
    全站熱搜

    alan790712 發表在 痞客邦 留言(0) 人氣()