QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#80708#5228. Alphabet AdventuringchenqingboruiAC ✓5462ms145076kbC++234.2kb2023-02-24 21:39:092023-02-24 21:39:11

Judging History

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

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-02-24 21:39:11]
  • 评测
  • 测评结果:AC
  • 用时:5462ms
  • 内存:145076kb
  • [2023-02-24 21:39:09]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;
constexpr int N = 6e5 + 10, S = 26;
int T, n, q, G[N][S];
namespace LCT {
	#define ls son[u][0]
	#define rs son[u][1]
	bool check(const array<int, S> &x, const array<int, S> &y) {
		for(int i = 0; i < S; i ++) if((x[i] | y[i]) != y[i]) return false;
		return true;
	}
	int rev[N], son[N][2], fa[N], sz[N], pre[N], suf[N], deg[N], par[N];
	array<int, S> f[N], g[N];
	inline bool isroot(int u) {return son[fa[u]][0] != u && son[fa[u]][1] != u;}
	inline bool type(int u) {return son[fa[u]][1] == u;}
	void up(int u) {
		sz[u] = sz[ls] + sz[rs] + 1;
		for(int i = 0; i < S; i ++) f[u][i] = f[ls][i] | f[rs][i];
		if(~pre[u]) f[u][pre[u]] |= deg[u];
		for(int i = 0; i < S; i ++) g[u][i] = g[ls][i] | g[rs][i];
		if(~suf[u]) g[u][suf[u]] |= deg[u];
	}
	void seta(int u) {
		if(!u) return ;
		swap(ls, rs), swap(f[u], g[u]), swap(pre[u], suf[u]), par[u] = pre[u];
		rev[u] ^= 1;
	}
	void dw(int u) {
		if(rev[u]) seta(ls), seta(rs), rev[u] = 0;
	}
	void rot(int u) {
		int f = fa[u], g = fa[f], k = type(u), w = son[u][!k];
		if(!isroot(f)) son[g][type(f)] = u; fa[u] = g;
		if(w) fa[w] = f; son[f][k] = w;
		son[u][!k] = f, fa[f] = u;
		up(f);
	}
	void pushall(int u) {
		if(!isroot(u)) pushall(fa[u]);
		dw(u);
	}
	void splay(int u) {
		pushall(u);
		while(!isroot(u)) {
			int f = fa[u];
			if(!isroot(f)) rot(type(u) == type(f) ? f : u);
			rot(u);
		}
		up(u);
	}
	int findmin(int u) {
		while(ls) dw(u), u = ls;
		splay(u);
		return u;
	}
	void access(int u) {
		for(int x = 0; u; u = fa[x = u]) {
			splay(u);
			int y = rs; rs = 0, suf[u] = -1;
			if(y) {
				int v = findmin(y);
				pre[v] = -1, up(v);
				deg[u] += 1 << par[v];
			}
			if(x) {
				int v = findmin(x);
				pre[v] = par[v];
				suf[u] = par[v];
				deg[u] -= 1ll << par[v];
				up(v);
				rs = v;
			}
			up(u);
		}
	}
	void link(int u, int v, int w) {
		access(v);
		fa[u] = v, par[u] = w, sz[u] = 1;
		pre[u] = suf[u] = -1;
		deg[v] += 1 << w;
	}
	int find(int u, const array<int, S> &s) {
		while(1) {
			dw(u);
			if(check(g[ls], s)) {
				if(~suf[u] && (s[suf[u]] & deg[u]) == deg[u]) {
					if(!rs) return u;
					u = rs;
				}
				else return u;
			} else {
				u = ls;
			}
		}
	}
	void makeroot(int u) {
		access(u), splay(u), seta(u);
	}
	int kth(int u, int k) {
		dw(u);
		if(k <= sz[ls]) return kth(ls, k);
		else if(k == sz[ls] + 1) return u;
		else return kth(rs, k - sz[ls] - 1);
	}
	#undef ls
	#undef rs
}
using namespace LCT;
int ask(int u, const array<int, S> &s) {
	makeroot(u);
	int v;
	for(; ~u;) {
		splay(u);
		v = find(u, s);
		u = -1;
		for(int i = 0, p = -1; i < S; i ++) if(deg[v] >> i & 1) {
			if(!~p || s[i] >> p & 1) u = G[v][i], p = i;
		}
	}
	return v;
}
int query(int u, int k, string str) {
	array<int, S> s;
	for(int i = 0; i < S; i ++) s[i] = 0;
	for(int i = 0; i < str.size(); i ++) {
		for(int j = i; j < str.size(); j ++) s[str[i] - 'A'] |= 1 << str[j] - 'A';
	}
	int v = ask(u, s);
	access(v), splay(v);
	int ans = kth(v, min(k, sz[v]));
	splay(ans);
	return ans;
}
void dfs(int u, int p) {
	pre[u] = suf[u] = par[u] = -1; sz[u] = 1;
	for(int i = 0; i < S; i ++) if(G[u][i]) {
		int v = G[u][i];
		if(v == p) continue;
		dfs(v, u);
		par[v] = i, fa[v] = u, deg[u] += 1 << i;
	}
}
int main() {
	// freopen("in.txt", "r", stdin);
	ios::sync_with_stdio(false), cin.tie(0);
	for(cin >> T; T; T --) {
		cin >> n;
		static int cases = 0;
		cout << "Case #" << ++ cases << ": ";
		for(int i = 1; i < n; i ++) {
			int u, v; char w;
			cin >> u >> v >> w;
			w -= 'A';
			G[u][w] = v, G[v][w] = u;
		}
		dfs(1, -1);
		int cnt = n;
		cin >> q;
		for(int i = 0; i < q; i ++) {
			int opt;
			cin >> opt;
			if(opt == 1) {
				int u = ++ cnt, v; char w;
				cin >> v >> w;
				w -= 'A';
				G[u][w] = v, G[v][w] = u;
				link(u, v, w);
			} else {
				int u, k;
				string str;
				cin >> u >> k >> str;
				cout << query(u, k + 1, str) << ' ';
			}
		}
		cout << '\n';
		for(int i = 1; i <= cnt; i ++) {
			for(int j = 0; j < S; j ++) f[i][j] = g[i][j] = G[i][j] = 0;
			son[i][0] = son[i][1] = fa[i] = sz[i] = 0;
			rev[i] = pre[i] = suf[i] = par[i] = deg[i] = 0;
		}
	}
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 5462ms
memory: 145076kb

input:

20
7
6 7 W
5 3 H
3 1 J
3 2 I
6 3 B
4 3 C
12
2 4 5 HBCJIW
2 1 4 JICWBH
2 6 2 JHWBCI
1 2 J
2 1 3 WHJICB
2 7 5 WJCBHI
2 7 5 IHWCJB
2 7 3 WCHIBJ
2 4 2 HJBWCI
1 1 K
2 7 6 WHIJKBC
2 2 3 BWKHJIC
13
2 7 P
13 5 E
12 11 K
2 13 R
2 11 S
6 1 Y
13 3 T
6 13 A
4 3 I
7 9 Z
8 5 S
11 10 A
35
2 7 8 ASPTIZYREK
2 11 6 I...

output:

Case #1: 5 2 7 5 1 8 4 5 5 8 
Case #2: 10 9 4 8 10 1 1 9 8 1 9 4 4 13 1 16 13 17 13 15 1 12 1 20 7 1 19 14 
Case #3: 30 7 23 20 28 20 31 2 2 12 2 2 
Case #4: 9 20 35 25 4 3 36 6 2 29 55 18 20 21 18 21 20 31 17 50 25 14 29 50 48 47 51 51 5 55 55 44 6 21 35 
Case #5: 24 57 56 61 34 17 21 64 40 17 31 2...

result:

ok 20 lines