Submission #67619

#TimeUsernameProblemLanguageResultExecution timeMemory
67619top34051Collapse (JOI18_collapse)C++17
100 / 100
8042 ms287872 KiB
//subtask3
#include "collapse.h"
#include<bits/stdc++.h>
using namespace std;

#define pii pair<int,int>
#define X first
#define Y second
const int maxn = 1e5 + 5;
const int sq = 320;

class DSU {
public:
	int n,com;
	int head[maxn], sz[maxn];
	stack<pii> stk;

	void init(int _n) {
		n = com = _n;
		for(int i=0;i<n;i++) {
			head[i] = i;
			sz[i] = 1;
		}
	}

	int findhead(int x) {
		if(x==head[x]) return x;
		return findhead(head[x]);
	}

	void add_edge(int u, int v) {
		int x = findhead(u), y = findhead(v);
		if(sz[x] > sz[y]) swap(x,y);
		stk.push({x,y});
		if(x!=y) {
			head[x] = y;
			sz[y] += sz[x];
			com--;
		}
	}

	void pop_edge() {
		int x = stk.top().X, y = stk.top().Y; stk.pop();
		if(x!=y) {
            head[x] = x;
            sz[y] -= sz[x];
            com++;
		}
	}

	int size() {
	    return com;
	}
} dsu;

struct trp {
	int x,y,id;
};

int n,m,q;
int ft[maxn];
map<pii,int> occur;

vector<trp> op;
vector<int> good, amb;
vector<int> ask[maxn];
int ans[maxn];

bool cmpL(trp a, trp b) {
    if(a.y != b.y) return a.y < b.y;
    return a.id < b.id;
}

bool cmpR(trp a, trp b) {
    if(a.x != b.x) return a.x > b.x;
    return a.id < b.id;
}

vector<int> simulateCollapse(int N, vector<int> T, vector<int> X, vector<int> Y, vector<int> D, vector<int> P) {
	n = N; m = T.size(); q = D.size();
	for(int i=0;i<m;i++) {
		if(X[i]>Y[i]) swap(X[i],Y[i]);
		if(T[i]==0) {
			ft[i] = m-1;
			occur[{X[i],Y[i]}] = i;
		}
		else ft[occur[{X[i],Y[i]}]] = i-1;
	}

	for(int i=0;i<q;i++) ask[D[i]].push_back(i);

	for(int s=0;s<m;s+=sq) {
		int e = min(m,s+sq-1);

		//eliminate all invalid edge (ft[i] < s)
		vector<int> tmp;
		for(auto i : good) {
			if(ft[i] < s) continue;
			tmp.push_back(i);
		}
		good = tmp;

		//---------------------------------------------------------------------------

		op.clear(); amb.clear();
		for(int i=s;i<=e;i++) {
			for(auto x : ask[i]) op.push_back({P[x],P[x],x});
		}
		for(auto i : good) {
			if(ft[i]>=e) op.push_back({X[i],Y[i],-1});
			else amb.push_back(i);
		}
		for(int i=s;i<=e;i++) amb.push_back(i);

		sort(op.begin(),op.end(),cmpL);

		dsu.init(n);
		for(auto t : op) {
			int x = t.id;
			if(x<0) dsu.add_edge(t.x,t.y);
			else {
				int ex = 0;
				for(auto i : amb) {
					if(Y[i]<=t.x && i<=D[x] && D[x]<=ft[i]) {
						dsu.add_edge(X[i],Y[i]);
						ex++;
					}
				}
				ans[x] += dsu.size();
				while(ex--) dsu.pop_edge();
			}
		}

		//---------------------------------------------------------------------------

		op.clear();
		for(int i=s;i<=e;i++) {
			for(auto x : ask[i]) op.push_back({P[x]+1,P[x]+1,x});
		}
		for(auto i : good) {
			if(ft[i]>=e) op.push_back({X[i],Y[i],-1});
			else amb.push_back(i);
		}

		sort(op.begin(),op.end(),cmpR);

		dsu.init(n);
		for(auto t : op) {
			int x = t.id;
			if(x<0) dsu.add_edge(t.x,t.y);
			else {
				int ex = 0;
				for(auto i : amb) {
					if(t.y<=X[i] && i<=D[x] && D[x]<=ft[i]) {
						dsu.add_edge(X[i],Y[i]);
						ex++;
					}
				}
				ans[x] += dsu.size();
				while(ex--) dsu.pop_edge();
			}
		}

		//---------------------------------------------------------------------------

		for(int i=s;i<=e;i++) {
			if(T[i]==0) good.push_back(i);
		}

	}

	vector<int> vec;
	for(int i=0;i<q;i++) vec.push_back(ans[i]-n);
	return vec;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...