//generated by GPT-5.4 modified by hamamu namespace SlideMinSpace{ using ll=long long; template struct slideextreme{ /* スライドmin/max用の共通実装。 Compare は「後ろの要素が、新しく入る要素より劣っているか」を表す比較。 - 最大値を取りたいとき: less 例: data < x なら data は今後最大候補になれないので捨てる - 最小値を取りたいとき: greater 例: data > x なら data は今後最小候補になれないので捨てる deque の先頭には、常に現在ウィンドウの答えが来る。 */ deque> dq; //<値, 追加順 index> int headIdx=0; //現在ウィンドウ先頭の index int tailIdx=-1; //現在までに追加した末尾の index Compare comp=Compare(); slideextreme() = default; void push_back(const T &x){ // 後ろにある「今後絶対に答えになれない要素」を捨てる while (!dq.empty()){ const T &data=dq.back().first; if (comp(data,x)) dq.pop_back(); else break; } dq.emplace_back(x,++tailIdx); } void pop_front(){ assert(headIdx<=tailIdx); if (!dq.empty() && dq.front().second==headIdx) dq.pop_front(); headIdx++; } T get()const{ assert(!dq.empty()); return dq.front().first; } }; template using slidemax = slideextreme>; template using slidemin = slideextreme>; template vector slideextreme1d(const vector &A,ll w){ ll N=(ll)A.size(); assert(1<=w && w<=N); vector ret; slideextreme se; for (ll l=0,r=w-1; r vector slidemin1d(const vector &A,ll w){ return slideextreme1d>(A,w); } template vector slidemax1d(const vector &A,ll w){ return slideextreme1d>(A,w); } template vector> slideextreme2d(const vector> &A,ll h,ll w){ ll H=(ll)A.size(); ll W=H==0 ? 0 : (ll)A[0].size(); assert(1<=h && h<=H && 1<=w && w<=W); // まず各行に対して幅 w のスライドmin/maxを取る vector> rowAns(H); for (ll i=0; i(A[i],w); // 次に各列に対して高さ h のスライドmin/maxを取る vector> ret(H-h+1,vector(W-w+1)); for (ll j=0; j<(ll)rowAns[0].size(); ++j){ vector col; for (ll i=0; i colAns=slideextreme1d(col,h); assert((ll)colAns.size()==H-h+1); for (ll i=0; i<(ll)colAns.size(); ++i) ret[i][j]=colAns[i]; } return ret; } template vector> slidemin2d(const vector> &A,ll h,ll w){ return slideextreme2d>(A,h,w); } template vector> slidemax2d(const vector> &A,ll h,ll w){ return slideextreme2d>(A,h,w); } }//SlideMinSpace using SlideMinSpace::slidemin; using SlideMinSpace::slidemax; using SlideMinSpace::slidemin1d; using SlideMinSpace::slidemax1d; using SlideMinSpace::slidemin2d; using SlideMinSpace::slidemax2d; /* - ---- スライドmin/max ---- ウィンドウ末尾にデータを追加、先頭からデータを取り出すとし、 ウィンドウ内のmin/maxを答えられるデータ構造。O(N)。 slidemin sm; //min slidemax sm; //max sm.push_back(x); //ウィンドウ末尾にx追加 sm.pop_front(); //ウィンドウ先頭を削除 ll va=sm.get(); //ウィンドウ内min/maxを取得 - ---- 1D配列の固定幅スライドmin/max ---- vll mns=slidemin1d(A,w); //mns[i]: 左端A[i]、幅w内のmin vll mxs=slidemax1d(A,w); //mxs[i]: 〃 max - ---- 2D配列の固定矩形スライドmin/max ---- vvll mnss=slidemin2d(A,h,w); //mnss[i][j]: 左上Aij,サイズh*wの矩形内min vvll mxss=slidemax2d(A,h,w); //mxss[i][j]: 〃 max */