競技プログラミングのべんきょうきろく

ブログ名からひと目でわかる圧倒的チラ裏

STLのコンパレータを外部から決定する

C++STLはぼくがじりきでやるじっそうより「圧倒的」につおい!これは 使 わ な け れ ば な ら な い

Pairを比較しy・・・ できねー!糞!フ○○ク!

自作構造体にデータのセットとオペレータを仕込む?自分でPairの代替とか逐次つくるのはめんどい・・・

VC++ 11.0 を今使ってるけど、xstddef に lessという構造体があって、STL上でソート等で使う比較にはlessにあるオペレータ演算子operator()を呼び出して比較の判断をしてるらしい、Visual studioの定義に移動がわりと便利
//xstddef

		// TEMPLATE STRUCT less
template<class _Ty>
	struct less
		: public binary_function<_Ty, _Ty, bool>
	{	// functor for operator<
	bool operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator< to operands
		return (_Left < _Right);
		}
	};


operator()を無理やり書き換えよう!

lessの部分を書き換えたら今後がやばすぎるだろ!おい馬鹿やめr

構造体だけど : binary_function... とか書いてるので継承できるみたいなので、継承して自前でなんとかしよう

オーバーライトしてoperator()を無理やり書き換えたる


こんな斜め上な方法は使う人がいないのか、わりと資料が見つからなかった
ので、メモ
今回の場合は、Pairで左の要素は昇順、右の要素は降順にしたいとしておいて決定する。lessの実装をみるとわかるように、stringでもdoubleとかデフォルトで <が実装されてれば使えるはず。自作クラス、構造体ならoperator<を作るといける。

#include <iostream>
#include <queue>

using namespace std;
#define REP(i,a,n) for(int i=(a); i<(int)(n); i++)
#define rep(i,n) REP(i,0,n)


//ここからが、要点

//less の構造体を継承して
struct unti : less<pair<int,int>>
{
    //operator()をオーバーロード
    //ここでしたい計算の処理を決定する
    bool operator()(const pair<int,int>& a,const pair<int,int>& b) const
    {
        if (a.first != b.first)
        {
            return a.first > b.first; //昇順
        }
        else
        {
            return a.second < b.second; //降順
        }
    }
};



int main()
{

    //普通はテンプレートの3つ目にgreaterとか入れるけど作った構造体をいれる
    priority_queue<pair<int,int>,vector<pair<int,int>>,unti> pq;


//ここまで

    int n = 5;
    rep(i,n)
    {
        rep(j,n)
        {
            pq.push(make_pair(i,j));
        }
    }
    rep(i,n*n)
    {
        cout << pq.top().first << "  " << pq.top().second << endl;
        pq.pop();
    }
    return 0;
}

first,second をうまく並べて表示したのが下
実行結果

0  4
0  3
0  2
0  1
0  0
1  4
1  3
1  2
1  1
1  0
2  4
2  3
2  2
2  1
2  0
3  4
3  3
3  2
3  1
3  0
4  4
4  3
4  2
4  1
4  0

結局構造体の継承をしてるし実装が面倒なんだよなぁ
ただ、スニペット化さえすればなんとか・・・

ついでにC#のときだったら、comparisonとかにラムダ式をぶっこむとかすればいけた記憶がある。(場合によっては一行ですむ