Submission #1169093

#TimeUsernameProblemLanguageResultExecution timeMemory
1169093Troll321Inside information (BOI21_servers)C++20
5 / 100
3597 ms45900 KiB
#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<bool, bool> pbb;
const ll MAXN = 120000 + 5;
const ll MAXQ = 2*MAXN;
const ll LOG = 17;
const ll MAXLOG = LOG+5;

ll n, k;

pair<char, pll> query[MAXQ];
// {Type, {a, b}}

ll parr[MAXN], depth[MAXN], sz[MAXN], heavy[MAXN];
vector<ll> adjl[MAXN];

struct segment {
	ll root = 0;
	vector<ll> nodes, seg;
	vector<pll> range;
	// {L, R}
	vector<pbb> extend;
	// {Lext, Rext}

	ll getIdx(ll node) {
		return depth[node] - depth[root];
	}

	ll lb() {return 0;}
	ll rb() {return (ll)nodes.size()-1;}

	void addNode(ll node) {
		if(nodes.empty()) {root = node;}
		nodes.push_back(node);
	}

	void addEdge(ll idxa, ll idxb) {
		if(idxa > idxb) {swap(idxa,idxb);}

		// Extend A
		extend[idxa].se = ((range[idxb].se - range[idxb].fi) == 0);

		// Extend B
		extend[idxb].fi = ((range[idxa].se - range[idxa].fi) == 0);

		range[idxa].se = idxb;
		range[idxb].fi = idxa;
	}

	pll findL(ll idx) {
		if(extend[idx].fi && range[idx].fi != idx) {
			pll out = findL(range[idx].fi);
			range[idx].fi = out.fi;
			extend[idx].fi = out.se;
			return {range[idx].fi, extend[idx].fi};
		}
		return {range[idx].fi, extend[idx].fi};
	}
	// {Range, Ext}

	pll findR(ll idx) {
		if(extend[idx].se && range[idx].se != idx) {
			pll out = findR(range[idx].se);
			range[idx].se = out.fi;
			extend[idx].se = out.se;
			return {range[idx].se, extend[idx].se};
		}
		return {range[idx].se, extend[idx].se};
	}

	pll find(ll idx) {
		return {findL(idx).fi, findR(idx).fi};
	}

	bool data(ll idxa, ll idxb) {
		// Apakah idxb nyampe idxa
		pll out = find(idxb);
		return ((out.fi <= idxa && idxa <= out.se) ? true : false);
	}

	ll count(ll idxa) {
		pll out = find(idxa);
		return (out.se - out.fi + 1);
	}

	void build(ll pos, ll l, ll r) {
		if(l == r) {
			seg[pos] = 1;
			return ;
		}
		ll mid = (l+r)/2;
		build(pos*2, l, mid);
		build(pos*2+1, mid+1, r);
		seg[pos] = seg[pos*2] + seg[pos*2+1];
	}

	void init() {
		seg.resize(nodes.size()*4);
		for (int i = 0; i < nodes.size(); ++i) {
			range.push_back({i,i});
			extend.push_back({true,true});
		}
		build(1, lb(), rb());
	}

	void update(ll pos, ll l, ll r, ll idx, ll x) {
		if(l > idx || r < idx) {
			return ;
		}
		if(idx <= l && r <= idx) {
			seg[pos] = x;
			return ;			
		}
		ll mid = (l+r)/2;
		update(pos*2, l, mid, idx, x);
		update(pos*2+1, mid+1, r, idx, x);
		seg[pos] = seg[pos*2] + seg[pos*2+1];
	}

	ll query(ll pos, ll l, ll r, ll idxa, ll idxb) {
		if(l > idxb || r < idxa) {
			return 0;
		}
		if(idxa <= l && r <= idxb) {
			return seg[pos];
		}
		ll mid = (l+r)/2;
		return (
			query(pos*2, l, mid, idxa, idxb) +
			query(pos*2+1, mid+1, r, idxa, idxb)
		);
	}
};

segment segs[MAXN];
void dfs(ll now, ll par) {
	parr[now] = par;
	depth[now] = depth[par]+1;
	sz[now] = 1;

	for(ll nxt : adjl[now]) {
		if(nxt == par) {continue ;}
		dfs(nxt, now);
		sz[now] += sz[nxt];
	}
}

void addHeavy(ll node, ll hidx) {
	segs[hidx].addNode(node);
}

void hld(ll now, ll par) {
	ll mx = -1, nowHeavy = -1;
	for(ll nxt : adjl[now]) {
		if(nxt == par) {continue ;}
		if(sz[nxt] > mx) {
			mx = sz[nxt];
			nowHeavy = nxt;
		}
	}

	if(heavy[now] == 0) {
		if (now == par) {
			heavy[now] = nowHeavy;
			addHeavy(now, heavy[now]);
		} else {
			heavy[now] = now;
			addHeavy(par, heavy[now]);
			addHeavy(now, heavy[now]);
		}
	}

	if(nowHeavy != -1) {
		heavy[nowHeavy] = heavy[now];
		addHeavy(nowHeavy, heavy[now]);
	}

	for(ll nxt : adjl[now]) {
		if(nxt == par) {continue ;}
		hld(nxt, now);
	}
}

void initSegs() {
	for (int i = 1; i <= n; ++i) {
		if(segs[i].nodes.empty()) {continue ;}
		segs[i].init();
	}
}

void addEdge(ll a, ll b) {
	if(depth[a] < depth[b]) {swap(a, b);}
	segment* s = &segs[heavy[a]];
	(*s).addEdge((*s).getIdx(b), (*s).getIdx(a));

	while(true) {
		pll range = (*s).find(0);
		ll ncnt = (*s).query(1, (*s).lb(), (*s).rb(), range.fi, range.se);
		ll now = (*s).root;
		s = &segs[heavy[now]];

		(*s).update(1, (*s).lb(), (*s).rb(), (*s).getIdx(now), ncnt);

		if(heavy[(*s).root] == heavy[now]) {
			break ;
		}
	}
}

void ask(ll a, ll b) {
	// Apakah b mencapai a
	ll ans = -1;
	while(true) {
		if(heavy[a] == heavy[b]) {
			segment* s = &segs[heavy[a]];
			ll ida = (*s).getIdx(a);
			ll idb = (*s).getIdx(b);
			ll hasil = (*s).data(ida, idb);
			ans = hasil;
			break ;
		} else {
			if(depth[heavy[a]] < depth[heavy[b]]) {
				// Naikin B
				segment* s = &segs[heavy[b]];
				ll idb = (*s).getIdx(b);
				ll hasil = (*s).data(0, idb);
				ans = hasil;
				if(!hasil) {break ;}

				b = (*s).root;
			} else {
				// Naikin A
				segment* s = &segs[heavy[a]];
				ll ida = (*s).getIdx(a);
				ll hasil = (*s).data(ida, 0);
				ans = hasil;
				if(!hasil) {break ;}

				a = (*s).root;
			}
		}
	}
	cout << (ans ? "yes" : "no") << "\n";
}

void count(ll a) {
	ll ans = 0;

	while(true) {
		segment* s = &segs[heavy[a]];
		pll range = (*s).find((*s).getIdx(a));
		ll hasil = (*s).query(1, (*s).lb(), (*s).rb(), range.fi, range.se);
		ans += hasil;
		if(range.fi == 0) {
			if(heavy[(*s).root] == heavy[a]) {break ;}
			a = (*s).root;
		}
	}

	cout << ans << "\n";
}

void solve() {
	cin >> n >> k;

	for (int i = 1; i <= n+k-1; ++i) {
		cin >> query[i].fi;
		switch(query[i].fi) {
		case 'S':
			cin >> query[i].se.fi >> query[i].se.se;
			adjl[query[i].se.fi].push_back(query[i].se.se);
			adjl[query[i].se.se].push_back(query[i].se.fi);
			break ;
		case 'Q':
			cin >> query[i].se.fi >> query[i].se.se;
			break ;
		case 'C':
			cin >> query[i].se.fi;
			break ;
		}
	}

	dfs(1, 1);
	hld(1, 1);
	initSegs();

	for (int i = 1; i <= n+k-1; ++i) {
		switch(query[i].fi) {
		case 'S':
			addEdge(query[i].se.fi, query[i].se.se);
			break ;
		case 'Q':
			ask(query[i].se.fi, query[i].se.se);
			break ;
		case 'C':
			count(query[i].se.fi);
			break ;
		}
	}
}

int main() {
	// ios_base::sync_with_stdio(false); cin.tie(0);
	solve();
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...