結果
| 問題 |
No.1920 Territory
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-03-04 09:43:46 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,590 bytes |
| コンパイル時間 | 2,725 ms |
| コンパイル使用メモリ | 230,628 KB |
| 最終ジャッジ日時 | 2025-02-11 05:05:53 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge6 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 25 WA * 7 |
ソースコード
#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;
}
// 1-indexed
template<typename T>
struct BIT{
int n;
vector<T> bit;
BIT(int n_=0):n(n_),bit(n+1){}
T sum(int i){
T res=0;
for(;i>0;i-=(i&-i))res+=bit[i];
return res;
}
void add(int i,T a){
if(i==0)return;
for(;i<=n;i+=(i&-i)){bit[i]+=a;}
}
int lower_bound(T k){ // k<=sum(res)
if(k<=0)return 0;
int res=0,i=1;
while((i<<1)<=n)i<<=1;
for(;i;i>>=1){
if(res+i<=n&&bit[res+i]<k)k-=bit[res+=i];
}
return res+1;
}
};
struct UnionFind{
vector<int> par,num;
UnionFind(int n):par(n),num(n,1){
iota(par.begin(),par.end(),0); //include<numeric>
}
int find(int v){
return (par[v]==v)?v:(par[v]=find(par[v]));
}
void unite(int u,int v){
u=find(u),v=find(v);
if(u==v)return;
if(num[u]<num[v])swap(u,v);
num[u]+=num[v];
par[v]=u;
}
bool same(int u,int v){
return find(u) == find(v);
}
int size(int v){
return num[find(v)];
}
};
int main() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
const int N = 2e5+1;
int n,m; cin >> n >> m;
int res = -(n+m); // 共有点の数と連結成分数を足したのが答え
vector<pair<int,int>> yoko(N,{-1,-1});
vector<vector<pair<int,int>>> in(N),out(N);
for (int i = 0; i < n; ++i) {
int a,b,c; cin >> a >> b >> c;
yoko[a] = {b,c};
}
for (int i = 0; i < m; ++i) {
int a,b,c; cin >> a >> b >> c;
in[b].push_back({a,i});
out[c].push_back({a,i});
}
// 共有点の数を求める
{
BIT<int> bit(N);
for (int i = 0; i < N; ++i) {
for (auto j:in[i]) {
bit.add(j.first, 1);
}
if(yoko[i].first != -1) {
res += bit.sum(yoko[i].second);
res -= bit.sum(yoko[i].first-1);
}
for (auto j:out[i]) {
bit.add(j.first, -1);
}
}
}
// 連結成分の数を求める
{
UnionFind uf(n+m);
int id = m;
set<pair<int,int>> S,T;
for (int i = 0; i < N; ++i) {
for (auto j:in[i]) {
S.insert(j);
T.insert(j);
}
if(yoko[i].first != -1) {
auto [l,r] = yoko[i];
auto it = T.lower_bound({l,-1});
if(it != T.end() and it->first <= r) {
int d = it->second;
uf.unite(id, d);
it = S.lower_bound({l,-1});
pair<int,int> f,s;
if(it != S.end() and it->first <= r) f = *it;
while (it != S.end() and it->first <= r) {
s = *it;
uf.unite(id, it->second);
it = S.erase(it);
}
S.insert(f);
if (f != s) S.insert(s);
}
id++;
}
for (auto j:out[i]) {
if(S.find(j) != S.end()) S.erase(j);
T.erase(j);
}
}
for (int i = 0; i < n+m; ++i) {
if(uf.find(i) == i) res++;
}
}
cout << res << endl;
}