1070-FIMO squence

問題概要

日本語なので略

解法

前半部分と後半部分に考えて分けて考える.
前半部分は後入れ後出し,後半部分は後入れ先出しの構造になる.
前半部分について,x番目の最大値(最小値)を求めるのは今までの最大値(最小値)を記録すれば可能
後半部分については,単調増加(減少)になるように配列に数値を入れていくようにする.

実装(C++)

#include <iostream>
#include <deque>
#include <algorithm>
#include <iterator>
#include <cstdio>
using namespace std;
struct FIMO_seqence{
  struct first_half{
    deque<int> data;
    deque<int> MAX,MIN;
    void add(int x){
      data.push_back(x);
      if(data.size()==1u){
        MAX.push_back(x);
        MIN.push_back(x);
      }else{
        if(MAX.back()<x){
          MAX.push_back(x);
        }
        if(MIN.back()>x){
          MIN.push_back(x);
        }
      }
    }
    int remove(){
      int x=data.back();
      data.pop_back();
      if(MIN.back()==x)MIN.pop_back();
      if(MAX.back()==x)MAX.pop_back();
      return x;
    }
    int size() const{
      return data.size();
    }
  } fh;
  struct second_half{
    deque<int> data;
    deque<int> MAX,MIN;
    void add(int x){
      data.push_back(x);
      if(data.size()==1u){
        MAX.push_back(x);
        MIN.push_back(x);
      }else{
        while((!MAX.empty())&&MAX.back()<x){
          MAX.pop_back();
        }
        while((!MIN.empty())&&MIN.back()>x){
          MIN.pop_back();
        }
        MAX.push_back(x);
        MIN.push_back(x);
      }
    }
    int remove(){
      int x=data.front();
      data.pop_front();
      if(MIN.front()==x)MIN.pop_front();
      if(MAX.front()==x)MAX.pop_front();
      return x;
    }
    int size() const{
      return data.size();
    }
  } sh;
  int size(){
    return sh.size()+fh.size();
  }
  void add(int x){
    sh.add(x);
    if(sh.size()>fh.size()){
      fh.add(sh.remove());
    }
  }
  int remove(){
    int r=fh.remove();
    if(sh.size()>fh.size()){
      fh.add(sh.remove());
    }
    return r;
  }
  int min_fh(int x){
    return *(fh.MIN.end()-x);
  }
  int min_sh(int x){
    return *(sh.MIN.begin()+x-1);
  }
  int max_fh(int x){
    return *(fh.MAX.end()-x);
  }
  int max_sh(int x){
    return *(sh.MAX.begin()+x-1);
  }
};
int main() {
  while(1){
    int q;
    scanf("%d",&q);
    if(q==0)break;
    FIMO_seqence fimo;
    for(int i=0;i<q;i++){
      int qt,t;
      scanf("%d",&qt);
      switch(qt){
        case 0:
          scanf("%d",&t);
          fimo.add(t);
          break;
        case 1:
          printf("%d\n",fimo.remove());
          break;
        case 2:
          printf("%d\n",fimo.min_fh(1));
          break;
        case 3:
          printf("%d\n",fimo.min_sh(1));
          break;
        case 4:
          scanf("%d",&t);
          printf("%d\n",fimo.min_fh(t));
          break;
        case 5:
          scanf("%d",&t);
          printf("%d\n",fimo.min_sh(t));
          break;
        case 6:
          printf("%d\n",fimo.max_fh(1));
          break;
        case 7:
          printf("%d\n",fimo.max_sh(1));
          break;
        case 8:
          scanf("%d",&t);
          printf("%d\n",fimo.max_fh(t));
          break;
        case 9:
          scanf("%d",&t);
          printf("%d\n",fimo.max_sh(t));
          break;
      }
    }
    puts("end");
  }
  return 0;
}