結果
| 問題 |
No.1170 Never Want to Walk
|
| コンテスト | |
| ユーザー |
startcpp
|
| 提出日時 | 2020-08-14 23:04:37 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 389 ms / 2,000 ms |
| コード長 | 1,700 bytes |
| コンパイル時間 | 783 ms |
| コンパイル使用メモリ | 75,012 KB |
| 実行使用メモリ | 6,912 KB |
| 最終ジャッジ日時 | 2024-10-10 16:29:52 |
| 合計ジャッジ時間 | 7,522 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 37 |
ソースコード
//連結成分のみが重要
//例えば駅iから駅Li~Riへ辺を張るのは、駅Li-(Li+1)-…-Riと辺を張ったあと、iからLiへ辺を張る
//と置き換えても答えは変わらない(と思う)
//前者(直線グラフ)は隣り合う2駅間の辺の個数をimos法で求めればOK. 後者は愚直に.
//辺の数がO(N)くらいになるので、あとはUnion Findでやればよし。
//区間は尺取り4回やればO(N)で求まるけど、O(NlogN)かけて2分探索した方が楽なので、2分探索で実装.
#include <iostream>
#include <algorithm>
#include <vector>
#define rep(i, n) for(i = 0; i < n; i++)
using namespace std;
struct UF {
int par[200000];
int sz[200000];
void init() {
int i;
rep(i, 200000) {
par[i] = i;
sz[i] = 1;
}
}
int root(int x) { if (par[x] == x) return x; return par[x] = root(par[x]); }
void unit(int x, int y) { x = root(x); y = root(y); if (x != y) { par[x] = y; sz[y] += sz[x]; } }
int size(int x) { return sz[root(x)]; }
};
int n, a, b;
int x[200000];
int imos[252521];
UF uf;
int main() {
int i;
cin >> n >> a >> b;
rep(i, n) cin >> x[i];
uf.init();
rep(i, n) {
int l1 = lower_bound(x, x + n, x[i] - b) - x;
int r1 = upper_bound(x, x + n, x[i] - a) - x;
int l2 = lower_bound(x, x + n, x[i] + a) - x;
int r2 = upper_bound(x, x + n, x[i] + b) - x;
//[l1, r1)
if (l1 < r1) {
imos[l1]++;
imos[r1 - 1]--;
uf.unit(i, l1);
}
//[l2, r2)
if (l2 < r2) {
imos[l2]++;
imos[r2 - 1]--;
uf.unit(i, l2);
}
}
rep(i, n) imos[i + 1] += imos[i];
rep(i, n - 1) {
if (imos[i] > 0) {
uf.unit(i, i + 1);
}
}
rep(i, n) cout << uf.size(i) << endl;
return 0;
}
startcpp