//Sylwia Sapkowska
#include <bits/stdc++.h>
#pragma GCC optimize("O3", "unroll-loops")
using namespace std;
void __print(int x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << "'" << x << "'";}
void __print(const char *x) {cerr << '"' << x << '"';}
void __print(const string &x) {cerr << '"' << x << '"';}
void __print(bool x) {cerr << (x ? "true" : "false");}
template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ", "; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? ", " : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifdef LOCAL
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif
#define int long long
typedef pair<int, int> T;
const int oo = 1e18, oo2 = 1e9+7, K = 30;
const int mod = 998244353;
struct rec{
int a, b, c, d;
rec(){}
rec(int _a, int _b, int _c, int _d): a(_a), b(_b), c(_c), d(_d) {}
};
//no segtree challenge
void solve(){
int n, m; cin >> n >> m;
vector<rec>tab;
for (int i = 0; i<n; i++){
int a, b, c, d; cin >> a >> b >> c >> d;
tab.emplace_back(a, b, c, d);
}
vector<T>p(m);
vector<int>color(m);
for (int i = 0; i<m; i++){
cin >> p[i].first >> p[i].second >> color[i];
}
auto scaler = color;
sort(scaler.begin(), scaler.end());
scaler.erase(unique(scaler.begin(), scaler.end()), scaler.end());
for (int i = 0; i<m; i++) {
color[i] = lower_bound(scaler.begin(), scaler.end(), color[i]) - scaler.begin();
}
vector<T>sweep;
for (int i = 0; i<n; i++){
sweep.emplace_back(tab[i].a, i);
sweep.emplace_back(tab[i].c, i);
}
vector<int>ord(m);
iota(ord.begin(), ord.end(), 0);
sort(ord.begin(), ord.end(), [&](auto x, auto y){return p[x] < p[y];});
sort(sweep.begin(), sweep.end());
set<T>s; //{poczatek, indeks}
s.insert({0, -1});
auto process = [&](int l, int r, int id){
vector<int>fix;
T left = {-1, -1};
T right = {-1, -1};
debug(l, r, id);
auto now = prev(s.lower_bound({l, -oo}));
for (auto it = now; it != s.end() && it->first <= r; it++){
auto it2 = next(it);
int L = it->first;
int R = (it2 == s.end() ? oo2 : it2->first) - 1;
fix.emplace_back(L);
if (l <= L && R <= r) {
continue;
} else { //wystaje
if (L < l) left = {L, it->second}; //z lewej strony
if (R > r) right = {r+1, it->second};
}
}
for (auto ll: fix) s.erase(s.lower_bound({ll, -oo}));
s.insert({l, id});
if (left.first != -1) s.insert(left);
if (right.first != -1) s.insert(right);
debug(s);
};
//zrobic drzewo
auto inside_rec = [&](int i, int j){
auto [a, b, c, d] = tab[i];
auto [A, B, C, D] = tab[j];
//czy i w srodku j?
return (A <= a && c <= C && B <= b && d <= D);
};
vector<int>par(n, -1);
vector<bool>vis(n+1);
for (auto [x, i]: sweep){
int l = tab[i].b;
int r = tab[i].d;
if (!vis[i]){
vis[i] = 1;
auto it = prev(s.upper_bound({l, oo}));
if (it != s.end() && it->second != -1){
int id = it->second;
debug(l, it->first, i, id);
par[i] = (inside_rec(i, id) ? id : par[id]);
}
}
process(l, r, i);
}
debug(par);
s.clear();
s.insert({0, -1});
vector<int>where(m, -2);
int ptr = -1;
auto inside = [&](int i, int j) {
auto [x, y] = p[j];
return (tab[i].a <= x && x <= tab[i].c && tab[i].b <= y && y <= tab[i].d);
};
for (auto i: ord){
debug(i, p[i]);
while (ptr+1 < (int)sweep.size() && sweep[ptr+1].first <= p[i].first){
ptr++;
int id = sweep[ptr].second;
int l = tab[id].b;
int r = tab[id].d;
process(l, r, id);
}
auto it = prev(s.upper_bound({p[i].second, oo}));
if (it != s.end() && it->first <= p[i].second && it->second != -1){
int p = it->second;
where[i] = (inside(p, i) ? p : par[p]);
}
}
debug(where);
vector<vector<int>>C(n);
for (int i = 0; i<m; i++){
if (where[i] < 0) continue;
C[where[i]].emplace_back(color[i]);
}
vector<vector<int>>G(n);
for (int i = 0; i<n; i++) {
if (par[i] != -1){
G[par[i]].emplace_back(i);
debug(par[i], i);
}
}
vector<set<int>>now(n);
vector<int>ret(n);
function<void(int)>dfs = [&](int v){
int big = -1;
for (auto x: G[v]){
dfs(x);
if (big == -1 || (int)now[x].size() > (int)now[big].size()) big = x;
}
if (big == -1){
for (auto cc: C[v]) now[v].insert(cc);
debug(v, now[v]);
ret[v] = (int)now[v].size();
return;
}
swap(now[v], now[big]);
for (auto cc: C[v]) now[v].insert(cc);
for (auto x: G[v]){
if (x == big) continue;
for (auto val: now[x]) now[v].insert(val);
}
debug(v, now[v]);
ret[v] = (int)now[v].size();
};
for (int i = 0; i<n; i++){
if (par[i] == -1){
dfs(i);
}
}
for (auto x: ret) cout << x << "\n";
}
int32_t main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
while (t--) solve();
return 0;
}
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
90 ms |
10212 KB |
Output is correct |
2 |
Correct |
88 ms |
10924 KB |
Output is correct |
3 |
Correct |
0 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
108 ms |
12888 KB |
Output is correct |
2 |
Correct |
122 ms |
12316 KB |
Output is correct |
3 |
Correct |
0 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
186 ms |
22612 KB |
Output is correct |
2 |
Correct |
205 ms |
19704 KB |
Output is correct |
3 |
Correct |
0 ms |
320 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
334 ms |
36088 KB |
Output is correct |
2 |
Correct |
350 ms |
32000 KB |
Output is correct |
3 |
Correct |
0 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
329 ms |
34136 KB |
Output is correct |
2 |
Correct |
335 ms |
31616 KB |
Output is correct |
3 |
Correct |
1 ms |
360 KB |
Output is correct |