QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#553894#5668. Cell Nuclei DetectionBongoCatEnjoyer#TL 0ms3616kbC++145.8kb2024-09-08 22:24:032024-09-08 22:24:03

Judging History

你现在查看的是最新测评结果

  • [2024-09-08 22:24:03]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:3616kb
  • [2024-09-08 22:24:03]
  • 提交

answer

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

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;



bool dfs(int a, int L, vector<vi>& g, vi& btoa, vi& A, vi& B) {
	if (A[a] != L) return 0;
	A[a] = -1;
	for (int b : g[a]) if (B[b] == L + 1) {
		B[b] = 0;
		if (btoa[b] == -1 || dfs(btoa[b], L + 1, g, btoa, A, B))
			return btoa[b] = a, 1;
	}
	return 0;
}

int hopcroftKarp(vector<vi>& g, vi& btoa) {
	int res = 0;
	vi A(g.size()), B(btoa.size()), cur, next;
	for (;;) {
		fill(all(A), 0);
		fill(all(B), 0);
		/// Find the starting nodes for BFS (i.e. layer 0).
		cur.clear();
		for (int a : btoa) if(a != -1) A[a] = -1;
		rep(a,0,sz(g)) if(A[a] == 0) cur.push_back(a);
		/// Find all layers using bfs.
		for (int lay = 1;; lay++) {
			bool islast = 0;
			next.clear();
			for (int a : cur) for (int b : g[a]) {
				if (btoa[b] == -1) {
					B[b] = lay;
					islast = 1;
				}
				else if (btoa[b] != a && !B[b]) {
					B[b] = lay;
					next.push_back(btoa[b]);
				}
			}
			if (islast) break;
			if (next.empty()) return res;
			for (int a : next) A[a] = lay;
			cur.swap(next);
		}
		/// Use DFS to scan for augmenting paths.
		rep(a,0,sz(g))
			res += dfs(a, 0, g, btoa, A, B);
	}
}

struct P {
    int x,y;

    bool operator<(const P& other) const {
        if (x == other.x) {
            return y < other.y;
        }
        return x < other.x;
    }
};

void solve(){
    int n,m;
    cin >> n >> m;
    vector<pair<P,P>> rectA;
    vector<int> areaA;
    vector<pair<P,P>> rectB;


    // (point, isakhir, type index)
    vector<tuple<P, bool, bool, int> > allP;
    rep(i,0,n){
        int a,b,c,d;
        cin >> a >> b >> c >> d;
        rectA.push_back({{a,b},{c,d}});
        areaA.push_back((c-a)*(d-b));
        allP.push_back({{a,b},false, 0, i});
        allP.push_back({{c,d},true, 0, i});
    }
    rep(i,0,m){
        int a,b,c,d;
        cin >> a >> b >> c >> d;
        rectB.push_back({{a,b},{c,d}});
        allP.push_back({{a,b},false, 1, i});
        allP.push_back({{c,d},true, 1, i});
    }

    sort(all(allP));

    set<tuple<int, int>> activeA;
    set<tuple<int, int>> activeB;

    auto compare =  [](const tuple<int, int>& a, const int& b) {
        return get<0>(a) < b;
    };

    auto compare2 =  [](const int& a, const tuple<int, int>& b) {
        return a < get<0>(b);
    };

    vector<vi> intersect(n);
    vector<unordered_set<int>> sudah(n);
    vector<int> btoa(m,-1);

    for (auto [p, isAkhir, type, idx] : allP){
        // cout << p.x << "," << p.y << ") " << isAkhir << " " << type << " " << idx << endl;
        if (type == 0){
            auto& rA = rectA[idx];
            if (!isAkhir){
                auto lower = lower_bound(all(activeB),rectA[idx].first.y, compare); // log(50000)
                auto upper = upper_bound(all(activeB),rectA[idx].second.y, compare2); // log(50000)
                assert(distance(activeB.begin(),lower) <= distance(activeB.begin(),upper));
                for (;lower != upper;lower++){
                    auto [y2,idx2] = *lower;
                    auto& rB = rectB[idx2];
                    // cout << "intersect rectA " << idx << " and " << "rectB " << idx2 << endl;
                    int h = min(rA.second.y, rB.second.y) - max(rA.first.y, rB.first.y);
                    // cout << h << endl;
                    if (2 * h * (rB.second.x-p.x) >= areaA[idx]){
                        // cout << "ANJIIIIR rectA " << idx << " and " << "rectB" << idx2 << endl;
                        if (sudah[idx].count(idx2) == 0){
                            intersect[idx].push_back(idx2);
                            sudah[idx].insert(idx2);
                        }
                    }
                }
                activeA.insert({rA.first.y,idx}); // log(50000)
                activeA.insert({rA.second.y,idx}); // log(50000)
            } else {
                activeA.erase({rA.first.y,idx}); // log(50000)
                activeA.erase({rA.second.y,idx});  // log(50000)
            }
        } else {
            auto& rB = rectB[idx];
            if (!isAkhir){
                auto lower = lower_bound(all(activeA),rectB[idx].first.y, compare); // log(50000)
                auto upper = upper_bound(all(activeA),rectB[idx].second.y, compare2); // log(50000)
                assert(distance(activeA.begin(),lower) <= distance(activeA.begin(),upper));
                for (;lower != upper;lower++){
                    auto [y2,idx2] = *lower;
                    auto& rA = rectA[idx2];
                    // cout << "intersect rectB " << idx << " and " << "rectA " << idx2 << endl;
                    
                    int h = min(rA.second.y, rB.second.y) - max(rA.first.y, rB.first.y);
                    // cout << h << endl;
                    if (2 * h * (rA.second.x-p.x) >= areaA[idx2]){
                        // cout << "ANJIIIIR rectA " << idx2 << " and " << "rectB" << idx << endl;
                        if (sudah[idx2].count(idx) == 0){
                            intersect[idx2].push_back(idx);
                            sudah[idx2].insert(idx);
                        }
                    }
                }
                activeB.insert({rB.first.y,idx}); // log(50000)
                activeB.insert({rB.second.y,idx}); // log(50000)
            } else {
                activeB.erase({rB.first.y,idx}); // log(50000)
                activeB.erase({rB.second.y,idx}); // log(50000)
            }
        }
    }
    cout << hopcroftKarp(intersect, btoa) << endl;;

}


int main(){
    cin.tie(0)->sync_with_stdio(0);
    cin.exceptions(cin.failbit);

    int t;
    cin >> t;
    while (t--){
        solve();
    }
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3616kb

input:

3
2 2
1 1 3 3
3 3 5 5
2 2 4 4
4 4 6 6
2 3
1 1 3 3
3 3 5 5
1 3 3 5
2 1 4 5
3 1 5 3
3 3
1 1 2 2
2 2 3 3
3 3 4 4
1 1 3 3
2 2 4 4
3 3 5 5

output:

0
1
3

result:

ok 3 lines

Test #2:

score: 0
Accepted
time: 0ms
memory: 3504kb

input:

3
2 2
1 1 3 3
3 3 5 5
2 2 4 4
4 4 6 6
2 3
1 1 3 3
3 3 5 5
1 3 3 5
2 1 4 5
3 1 5 3
3 3
1 1 2 2
2 2 3 3
3 3 4 4
1 1 3 3
2 2 4 4
3 3 5 5

output:

0
1
3

result:

ok 3 lines

Test #3:

score: -100
Time Limit Exceeded

input:

5
50000 50000
0 0 4 4
4 0 8 4
8 0 12 4
12 0 16 4
16 0 20 4
20 0 24 4
24 0 28 4
28 0 32 4
32 0 36 4
36 0 40 4
40 0 44 4
44 0 48 4
48 0 52 4
52 0 56 4
56 0 60 4
60 0 64 4
64 0 68 4
68 0 72 4
72 0 76 4
76 0 80 4
80 0 84 4
84 0 88 4
88 0 92 4
92 0 96 4
96 0 100 4
100 0 104 4
104 0 108 4
108 0 112 4
112 ...

output:

50000
50000
0

result: