Problem:
問題 A : Koto Distance

問題文

Koto は言わずと知れた碁盤の目の街である．
この街は東西方向に W メートル，南北方向に H メートルに伸びる長方形の領域によってできている．
この街の西端から x メートル，南端から y メートルの点は (x,  y) と記される．
ここの街に住む人は古くから伝わる独自の文化を重んじており，その一つにKoto距離という変わった距離尺度がある．
2つの点 (x_1, y_1)，(x_2, y_2) の Koto 距離は，min(|x_1 - x_2|,  |y_1 - y_2|) によって定義される．

最近この街全体に Wifi を使えるようにする計画が立ち上がった．
現在の計画では，親機を N 個作ることになっている．
i 番目の親機は点 (x_i,  y_i) に設置され，Koto距離が w_i 以下の領域に対して Wifi を提供する．

親機を計画どおり建てた場合に，街の内部及び境界上に Wifi を提供できるかどうかを判定せよ．

なお，Koto距離は一般に三角不等式を満たさないため，距離の公理を満たさないということはここだけの秘密である．

入力形式

入力は以下の形式で与えられる．

N W H
x_1 y_1 w_1
...
x_N y_N w_N

出力形式

街の内部および境界上に Wifi を提供できるなら “Yes” を，そうでない場合は “No” を出力せよ．

制約

1 ≤ N ≤ 10^5

1 ≤ W ≤ 10^5

1 ≤ H ≤ 10^5

0 ≤ x_i ≤ W

0 ≤ y_i ≤ H

1 ≤ w_i ≤ 10^5

同一座標に親機は複数存在しない

入出力例

入力例 1

3 9 9
2 2 2
5 5 2
8 8 2

出力例 1

Yes

２番目の親機が提供するWifiの範囲は以下の通りである．

入力例 2

2 7 7
2 2 1
6 6 1

出力例 2

No

入力例 3

3 10 20
5 10 5
2 10 1
8 10 1

出力例 3

Yes

Solution in C++11 (judge verdict: Accepted)

// Template {{{
#include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)
using namespace std;
typedef long long LL;
 
template<typename T1, typename T2>
ostream& operator << (ostream& os, const pair<T1, T2>& p) {
    os << "(" << p.first << ", " << p.second << ")";
    return os;
}
 
template<typename T>
ostream& operator << (ostream& os, const vector<T>& v) {
    os << "{";
    for(int i = 0; i < v.size(); i++)
        os << v[i] << (i+1<v.size()?", ":"");
    os << "}";
    return os;
}
 
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
inline bool valid(int x, int w) { return 0 <= x && x < w; }
 
void iostream_init() {
    ios::sync_with_stdio(false);
    cin.tie(0);
}
//}}}
 
int main(){
    iostream_init();
    int N, W, H;
    cin >> N >> W >> H;
    vector<pair<int, int>> xs(N);
    vector<pair<int, int>> ys(N);
    REP(i, N){
        int x, y, w;
        cin >> x >> y >> w;
        xs[i] = make_pair(2*x, 2*w);
        ys[i] = make_pair(2*y, 2*w);
    }
 
    sort(xs.begin(), xs.end());
    sort(ys.begin(), ys.end());
 
    bool ans = false;
    W *= 2;
    H *= 2;
    {
        int cur = 0;
        bool ok = true;
        REP(i, W+1) {
            while(cur < N && abs(xs[cur].first - i) > xs[cur].second) {
                cur++;
            }
            if(cur == N){
                ok = false;
                break;
            }
        }
        ans = ans || ok;
    }
    {
        int cur = 0;
        bool ok = true;
        REP(i, H+1) {
            while(cur < N && abs(ys[cur].first - i) > ys[cur].second) {
                cur++;
            }
            if(cur == N){
                ok = false;
                break;
            }
        }
        ans = ans || ok;
    }
    cout << (ans ? "Yes" : "No") << endl;
    return 0;
}
 
/* vim:set foldmethod=marker: */