Problem:
座席 2 (Seats 2)
問題文
JOI 国では，今年プログラミングの世界大会が開かれることとなった．大会には
N
人の選手が参加予定であり，選手には
1
から
N
までの番号が付けられている．
各選手の出身国は
1
以上
10
9
以下の整数の番号で表され，選手
i
(
1 ≦ i ≦ N
) の出身国は国
C
i
である．
N
人の選手の出身国がすべて同じであることはない．
また，各選手の座席は直線状に並んでおり，選手
i
(
1 ≦ i ≦ N
) の座席は位置
X
i
にある．選手
i
(
1 ≦ i ≦ N
) と選手
j
(
1 ≦ j ≦ N
) の
座席の距離
は
|X
i
- X
j
|
である．ただし，
|x|
は
x
の絶対値を表す．
各選手は大会中他の選手と交流をするにあたって，自分とは出身国の異なる選手のうち，自分と座席が最も近い選手までの座席の距離を知りたい．
各選手の出身国と座席の位置の情報が与えられたとき，各選手
i
(
1 ≦ i ≦ N
) について，選手
i
とは出身国の異なる選手のうち，選手
i
との座席の距離が最も小さい選手までの座席の距離を出力するプログラムを作成せよ．
制約
2 ≦ N ≦ 300 000
．
1 ≦ C
i
≦ 10
9
(
1 ≦ i ≦ N
)．
1 ≦ X
i
≦ 10
9
(
1 ≦ i ≦ N
)．
N
人の選手の出身国がすべて同じであることはない．
入力される値はすべて整数である．
入力
入力は以下の形式で与えられる．
N
C
1
X
1
C
2
X
2
︙
C
N
X
N
出力
N
行出力せよ．
i
行目 (
1 ≦ i ≦ N
) には，選手
i
とは出身国の異なる選手のうち，選手
i
との座席の距離が最も小さい選手までの座席の距離を出力せよ．
入出力例
入力例 1
3
2 5
1 1
1 2
出力例 1
3
4
3
選手
1
の出身国は国
2
であり，選手
1
と出身国の異なる選手は選手
2, 3
である．これらの選手のうち，選手
1
との座席の距離が最も小さい選手は選手
3
であり，その座席の距離は
3
である．したがって，
1
行目には
3
を出力する．
選手
2
の出身国は国
1
であり，選手
2
と出身国の異なる選手は選手
1
のみである．選手
2
と選手
1
の座席の距離は
4
なので，
2
行目には
4
を出力する．
選手
3
の出身国は国
1
であり，選手
3
と出身国の異なる選手は選手
1
のみである．選手
3
と選手
1
の座席の距離は
3
なので，
3
行目には
3
を出力する．
入力例 2
5
1 1
2 4
2 14
3 10
2 2
出力例 2
1
3
4
4
1
入力例 3
3
1 1
2 1
1 1
出力例 3
0
0
0
同じ位置に複数の選手の座席があることもある．
情報オリンピック日本委員会
作『日本情報オリンピック第4回女性部門 本選 競技課題』

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct Seat {
    long long country, x;
    int idx;
    bool operator<(const Seat &o) const {
        if (x != o.x) return x < o.x;
        return country < o.country;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    vector<Seat> v(n);
    for (int i = 0; i < n; i++) {
        cin >> v[i].country >> v[i].x;
        v[i].idx = i;
    }
    sort(v.begin(), v.end());

    vector<long long> ls(n, -1), rs(n, -1);

    // 左→右
    int l = 0, r = 0;
    long long cur = v[0].country;
    while (r < n) {
        while (r < n && v[r].country == cur) r++;
        if (r == n) break;
        while (l < r) {
            ls[v[l].idx] = v[r].x - v[l].x;
            l++;
        }
        cur = v[r].country;
    }

    // 右→左
    r = n - 1, l = n - 1;
    cur = v[l].country;
    while (l >= 0) {
        while (l >= 0 && v[l].country == cur) l--;
        if (l < 0) break;
        while (l < r) {
            rs[v[r].idx] = v[r].x - v[l].x;
            r--;
        }
        cur = v[l].country;
    }

    // 出力
    for (int i = 0; i < n; i++) {
        if (ls[i] == -1) cout << rs[i] << "\n";
        else if (rs[i] == -1) cout << ls[i] << "\n";
        else cout << min(ls[i], rs[i]) << "\n";
    }
}
accuracy: 1
time_ms: 50
memory_kb: 15068
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>

struct Seat {
    int id;
    int posi;
    int cnty;
    int dist;

    Seat(int in_id, int in_posi, int in_cnty) {
        id = in_id;
        posi = in_posi;
        cnty = in_cnty;
        dist = 0;
    }
};

bool comp(const Seat& a, const Seat& b) {
    if (a.posi != b.posi)
        return a.posi < b.posi;
    else if (a.cnty != b.cnty)
        return a.cnty < b.cnty;
    else
        return a.id < b.id;
}

bool comp2(const Seat& a, const Seat& b) {
    return a.id < b.id;
}

int binarySearch(int key, std::vector<std::vector<int>> A, int left, int right) {
    int mid;

    while (left <= right) {
        mid = left + (right - left + 1) / 2;
        if (A[mid][0] == key)
            return mid;
        else if (A[mid][0] < key)
            left = mid + 1;
        else
            right = mid - 1;
    }
}

int main()
{
    int N;
    std::cin >> N;
    int in_cnty, in_posi;
    std::vector<Seat> seat;
           
    for (int i = 0; i < N; i++) {
        std::cin >> in_cnty >> in_posi;
        seat.push_back(Seat(i, in_posi, in_cnty));
    }
    
    std::sort(seat.begin(), seat.end(), comp);

//    for (int i = 0; i < seat.size(); i++)
//        std::cout << seat[i].id << " " << seat[i].cnty << " " << seat[i].posi << std::endl;

    int idx = 0, prev = -1000000005;
    for (int i = 1; i < seat.size(); i++)
        if (seat[idx].cnty != seat[i].cnty) {
            while (idx < i) {
                seat[idx].dist = std::min(seat[idx].posi - prev, seat[i].posi - seat[idx].posi);
                ++idx;
            }
            prev = seat[i - 1].posi;
        }
    for (int i = idx; i < seat.size(); i++)
        seat[i].dist = seat[i].posi - prev;
            
    std::sort(seat.begin(), seat.end(), comp2);

//    for (int i = 0; i < seat.size(); i++)
//        std::cout << seat[i].id << " " << seat[i].cnty << " " << seat[i].posi 
//        << " " << seat[i].dist << std::endl;

    for (int i = 0; i < seat.size(); i++)
        std::cout << seat[i].dist << std::endl;

    return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 13276
final_rank: 4

code_snippet: #include <iostream>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
long long int ls[300003];
long long int rs[300003];

struct E{
	int p,no;
	long long int x;
	bool operator<(const E& e1)const{
		if(x!=e1.x)return x<e1.x;
		return p<e1.p;
	}
};

int main() {
	memset(ls,-1,sizeof(ls));
	memset(rs,-1,sizeof(rs));
	int n;
	cin>>n;
	vector<E> vs;
	for(int i=0;i<n;i++){
		E e1;
		cin>>e1.p>>e1.x;
		e1.no=i;
		vs.push_back(e1);
	}
	sort(vs.begin(),vs.end());
	int l=0;
	int r=0;
	int p=vs[0].p;
	while(r<n){
		while(r<n){
			if(p==vs[r].p){
				r++;
			}else{
				break;
			}
			
		}
		if(n<=r)break;
		while(l<r){
			ls[vs[l].no]=vs[r].x-vs[l].x;
			l++;
		}
		p=vs[r].p;
	}
	r=n-1;
	l=n-1;
	p=vs[l].p;
	while(0<=l){
		while(0<=l){
			if(p==vs[l].p){
				l--;
			}else{
				break;
			}
		}
		if(l<0)break;
		while(l<r){
			rs[vs[r].no]=vs[r].x-vs[l].x;
			r--;
		}
		p=vs[l].p;
	}
	
	for(int i=0;i<n;i++){
		//cout<<ls[i]<<" "<<rs[i];
		if(ls[i]==-1){
			cout<<rs[i];
		}else if(rs[i]==-1){
			cout<<ls[i];
		}else{
			cout<<min(ls[i],rs[i]);
		}
		cout<<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 18004
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
//#define MOD 998244353
#define MOD 1000000007
#define EPS 0.000000001


#define SIZE 300005

struct Info{

	int loc;
};

int number = 0,ANS[SIZE];
map<int,int> IND,ALL;
vector<int> V[SIZE];
Info info[SIZE];

int getIndex(int num){

	auto at = IND.find(num);
	if(at == IND.end()){
		IND[num] = number++;
	}
	return IND[num];
}

int main(){

	int N;
	scanf("%d",&N);

	int C;

	for(int i = 0; i < N; i++){

		scanf("%d %d",&C,&info[i].loc);
		int tmp_ind = getIndex(C);

		ALL[info[i].loc] += 1;

		V[tmp_ind].push_back(i);
	}

	for(int i = 0; i < number; i++){

		//自分のグループの位置を消す
		for(int k = 0; k < V[i].size(); k++){
			int tmp_ind = V[i][k];
			ALL[info[tmp_ind].loc]--;
			if(ALL[info[tmp_ind].loc] == 0){

				ALL.erase(info[tmp_ind].loc);
			}
		}

		for(int k = 0; k < V[i].size(); k++){

			int mini = BIG_NUM;
			int tmp_ind = V[i][k];

			auto at = ALL.lower_bound(info[tmp_ind].loc);
			if(at != ALL.end()){

				mini = at->first - info[tmp_ind].loc;
			}
			if(at != ALL.begin()){
				at--;
				chmin(mini,info[tmp_ind].loc- at->first);
			}

			ANS[tmp_ind] = mini;
		}

		//自分のグループの位置を戻す
		for(int k = 0; k < V[i].size(); k++){
			int tmp_ind = V[i][k];
			ALL[info[tmp_ind].loc]++;
		}
	}

	for(int i = 0; i < N; i++){

		printf("%d\n",ANS[i]);
	}

	return 0;
}
accuracy: 1
time_ms: 600
memory_kb: 50132
final_rank: 7

code_snippet: #include <iostream>
#include <cstdint>
#include <vector>
#include <set>
#include <unordered_map>

using namespace std;

template<typename T> constexpr T chmin(T& variable, const T value) noexcept
{
	if (variable < value) return variable;
	else return (variable = value);
}

int main()
{
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	uint32_t N, i, j;
	cin >> N;
	vector<uint32_t> C(N), X(N);
	for (i = 0; i != N; ++i) cin >> C[i] >> X[i];

	multiset<uint32_t> seats;
	unordered_map<uint32_t, uint32_t> country_id_for;
	vector<vector<pair<uint32_t, uint32_t>>> players_from;
	for (i = 0; i != N; ++i)
	{
		if (!country_id_for.contains(C[i]))
		{
			country_id_for.insert({ C[i], country_id_for.size() });
			players_from.emplace_back();
		}

		seats.insert(X[i]);
		players_from[country_id_for[C[i]]].emplace_back(X[i], i);
	}

	vector<uint32_t> ans(N, UINT32_MAX);
	for (i = 0; i != players_from.size(); ++i)
	{
		for (j = 0; j != players_from[i].size(); ++j)
			seats.erase(seats.find(players_from[i][j].first));

		for (j = 0; j != players_from[i].size(); ++j)
		{
			const auto itr = seats.lower_bound(players_from[i][j].first);
			if (itr != seats.begin())
				chmin(ans[players_from[i][j].second], players_from[i][j].first - *prev(itr));
			if (itr != seats.end())
				chmin(ans[players_from[i][j].second], *itr - players_from[i][j].first);
		}

		for (j = 0; j != players_from[i].size(); ++j)
			seats.insert(players_from[i][j].first);
	}

	for (i = 0; i != N; ++i)
		cout << ans[i] << '\n';

	return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 51180
final_rank: 6

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<int> c(n), x(n), idx(n);
    for (int i = 0; i < n; i++) {
        cin >> c[i] >> x[i];
        idx[i] = i;
    }
    sort(idx.begin(), idx.end(), [&](auto i, auto j) { return x[i] < x[j]; });

    vector<int> res(n, 2e9);
    int c1 = -1, c2 = -1;
    int d1 = -1e9, d2 = -1e9;
    for (int i = 0; i < n; i++) {
        int j = idx[i];
        if (c1 != c[j]) {
            res[j] = min(res[j], x[j] - d1);
            c2 = c1, d2 = d1;
            c1 = c[j], d1 = x[j];
        } else {
            res[j] = min(res[j], x[j] - d2);
            c1 = c[j], d1 = x[j];
        }
    }
    c1 = -1, c2 = -1;
    d1 = 2e9, d2 = 2e9;
    for (int i = n - 1; i >= 0; i--) {
        int j = idx[i];
        if (c1 != c[j]) {
            res[j] = min(res[j], d1 - x[j]);
            c2 = c1, d2 = d1;
            c1 = c[j], d1 = x[j];
        } else {
            res[j] = min(res[j], d2 - x[j]);
            c1 = c[j], d1 = x[j];
        }
    }

    for (int i = 0; i < n; i++) {
        cout << res[i] << "\n";
    }
}
accuracy: 1
time_ms: 70
memory_kb: 7852
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;

int main(){
    int N;
    cin>>N;
    vector<ll> C(N),X(N),AN(N,2e18);
    map<ll,vector<ll>> M;
    multiset<ll> S;
    S.insert(-1e18);
    S.insert(1e18);
    for(ll i=0;i<N;i++){
        cin>>C[i]>>X[i];
        M[C[i]].push_back(i);
        S.insert(X[i]);
    }
    for(auto m:M){
        for(auto x:m.second)S.erase(S.find(X[x]));
        for(auto x:m.second){
            AN[x]=min(AN[x],*(S.lower_bound(X[x]))-X[x]);
            AN[x]=min(AN[x],X[x]-*(prev(S.lower_bound(X[x]))));
        }
        for(auto x:m.second)S.insert(X[x]);
    }
    for(int i=0;i<N;i++)cout<<AN[i]<<endl;

}
accuracy: 1
time_ms: 880
memory_kb: 56876
final_rank: 8

code_snippet: // AOJ #787
// Seats 2 2025.1.11

#include <bits/stdc++.h>
using namespace std;

// 選手の情報を保持する構造体
struct Seat {
    long long country; // 国番号
    long long x;       // 座席の位置
    int idx;           // 元の入力順(0-based)
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    int N;
    cin >> N;

    vector<Seat> seats(N);
    for(int i = 0; i < N; i++){
        long long c, x;
        cin >> c >> x;
        seats[i].country = c;
        seats[i].x       = x;
        seats[i].idx     = i;  // 入力順を保持
    }

    // 1. 座席を位置 X でソート
    sort(seats.begin(), seats.end(), [](const Seat &a, const Seat &b){
        return a.x < b.x;
    });

    // 2. ソート後、同じ国が連続する区間を「ブロック」とする
    //    blockId[i] = 座席 i が属するブロック番号
    vector<int> blockId(N);
    vector<long long> blockCountry;    // 各ブロックの国番号
    vector<int>       blockStart;      // 各ブロックの開始インデックス(ソート後)
    vector<int>       blockEnd;        // 各ブロックの終了インデックス(ソート後)

    // 最初のブロック設定
    int blockCount = 0;
    blockId[0] = 0;
    blockCountry.push_back(seats[0].country);
    blockStart.push_back(0);

    // ブロック分割
    for (int i = 1; i < N; i++) {
        if (seats[i].country == seats[i - 1].country) {
            // 同じ国なので同じブロック
            blockId[i] = blockCount;
        } else {
            // 国が変わったので前のブロックを閉じて新ブロック開始
            blockEnd.push_back(i - 1);  // 直前でブロック終了
            blockCount++;
            blockId[i] = blockCount;
            blockCountry.push_back(seats[i].country);
            blockStart.push_back(i);
        }
    }
    // 最後のブロックを閉じる
    blockEnd.push_back(N - 1);
    blockCount++;

    // ブロックの「左端」「右端」の座席位置を取得 (計算しやすいように)
    vector<long long> blockLeftPos(blockCount), blockRightPos(blockCount);
    for (int b = 0; b < blockCount; b++){
        blockLeftPos[b]  = seats[ blockStart[b] ].x;  // ブロック先頭の位置
        blockRightPos[b] = seats[ blockEnd[b] ].x;    // ブロック末尾の位置
    }

    // 3. 距離計算用の配列 (元の入力順に格納する)
    vector<long long> answer(N, 0LL);

    // 各ブロック内の座席について、左右ブロックとの距離の最小を答えとする
    //   distLeft = x_i - blockRightPos[b-1]  (b > 0 のとき)
    //   distRight = blockLeftPos[b+1] - x_i (b < blockCount-1 のとき)
    //   同じ座席位置なら距離 0 となる可能性がある
    for (int b = 0; b < blockCount; b++) {
        for (int i = blockStart[b]; i <= blockEnd[b]; i++) {
            long long x_i = seats[i].x;
            long long distLeft = LLONG_MAX;
            long long distRight = LLONG_MAX;

            if (b > 0) {
                distLeft = x_i - blockRightPos[b - 1];
                if (distLeft < 0) distLeft = 0;  // 同じ位置なら 0
            }
            if (b < blockCount - 1) {
                distRight = blockLeftPos[b + 1] - x_i;
                if (distRight < 0) distRight = 0; // 同じ位置なら 0
            }

            long long dist = min(distLeft, distRight);
            answer[ seats[i].idx ] = dist;
        }
    }

    // 4. 結果を元の入力順で出力
    for (int i = 0; i < N; i++){
        cout << answer[i] << "\n";
    }

    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 26696
final_rank: 3