题目描述:
思路: 并查集区间染色 + 离散化
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
//#define int long long
#define ios ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
const int N = 2e5+5;
int n, X, Y;
struct Seg{
int x, y, l;
bool operator < (const Seg &t) const{
return t.y < this->y;
}
};
struct DSU{
vector<int > fa, sz;
DSU(int n){
init(n);
}
void init(int n){
fa.resize(n);
iota(fa.begin(), fa.end(), 0);
sz.assign(n, 1);
}
int find(int x){
if(fa[x] != x){
fa[x] = find(fa[x]);
}
return x;
}
int size(int x){
return sz[find(x)];
}
bool merge(int x, int y){
// (x) <- (y) y集合加入x集合
x = find(x);
y = find(y);
if(x == y){
return false;
}
sz[x] += sz[y];
fa[y] = x;
return true;
}
bool same(int x, int y){
return find(x) == find(y);
}
};
void solve(){
cin >> n >> X >> Y;
vector<Seg> seg;
for(int i = 1; i <= n; i++){
int x, y, l;
cin >> x >> y >> l;
seg.push_back(Seg{x, y, l});
}
sort(seg.begin(), seg.end());
vector<double > p(2 * n);
for(int i = 0; i < n; i++){
auto [x, y, l] = seg[i];
//cout << x <<" " << y <<" " << l << endl;
auto cal = [&](int x, int y) -> double{
if(x == X) return x;
else return (1.0 * x * Y - 1.0*X * y)/(Y - y);
};
p[i] = cal(x , y);
p[i + n] = cal(x + l, y);
}
auto v = p;
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
int m = v.size();
vector<bool > vis(m);
DSU dsu(m);
int ans = 0;
for(int i = 0; i < n; i++){
auto find = [&](double x) -> int{
return lower_bound(v.begin(), v.end(), x) - v.begin();
};
int l = find(p[i]);
int r = find(p[i + n]);
bool flag = false;
for(int j = dsu.find(l); j < r; j = dsu.find(j + 1)){
if(!vis[j]){
flag = true;
dsu.merge(j + 1, j); // j的右边界更新为j + 1 的右边界
vis[j] = 1;
}
}
ans += flag;
}
cout << ans << endl;
}
signed main(){
ios; int _;
_ = 1; //cin >> _;
while(_--){
solve();
}
return 0;
}