QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#473531#1163. Another Tree Queries Problemaqz180321WA 83ms46412kbC++145.8kb2024-07-12 08:36:562024-07-12 08:36:57

Judging History

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

  • [2024-07-12 08:36:57]
  • 评测
  • 测评结果:WA
  • 用时:83ms
  • 内存:46412kb
  • [2024-07-12 08:36:56]
  • 提交

answer

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector> 

const int N = 2e5 + 10;
int n, q;
std::vector < int > edge[N];

int dfn[N], dfntot, id[N];
int dep[N], son[N], size[N], fa[N], top[N], st[30][N];

struct seg1 {
	int sum[N << 2], lazya[N << 2], lazyb[N << 2];
	
	void add (int pos, int l, int r, int a, int b) {
		sum[pos] += (l + r) * a * (r - l + 1) / 2;
		sum[pos] += (r - l + 1) * b;
		lazya[pos] += a;
		lazyb[pos] += b;
	}
	
	void update (int pos) {
		sum[pos] = sum[pos << 1] + sum[pos << 1 | 1];
	}
	
	void push (int pos, int l, int r) {
		if (lazya[pos] || lazyb[pos]) {
			int mid = (l + r) >> 1;
			add (pos << 1, l, mid, lazya[pos], lazyb[pos]);
			add (pos << 1 | 1, mid + 1, r, lazya[pos], lazyb[pos]);
			lazya[pos] = lazyb[pos] = 0;
		}
	}
	
	void build (int pos, int l, int r) {
		sum[pos] = lazya[pos] = lazyb[pos] = 0;
		if (l == r) return ;
		int mid = (l + r) >> 1;
		build (pos << 1, l, mid);
		build (pos << 1 | 1, mid + 1, r);
	}
	
	void modify (int pos, int l, int r, int x, int y, int a, int b) {
		if (x <= l && r <= y) {
			add (pos, l, r, a, b);
			return ;
		}
		push (pos, l, r);
		int mid = (l + r) >> 1;
		if (x <= mid) modify (pos << 1, l, mid, x, y, a, b);
		if (y >= mid + 1) modify (pos << 1 | 1, mid + 1, r, x, y, a, b);
		update (pos); 
	}
	
	int query (int pos, int l, int r, int x, int y) {
		if (x <= l && r <= y) return sum[pos];
		push (pos, l, r);
		int mid = (l + r) >> 1, ans = 0;
		if (x <= mid) ans += query (pos << 1, l, mid, x, y);
		if (y >= mid + 1) ans += query (pos << 1 | 1, mid + 1, r, x, y);
		return ans;
	}
} tr1;

struct seg2 {
	int sz[N << 2], sum[N << 2];
	int lazy[N << 2];
	
	void add (int pos, int k) {
		sum[pos] += sz[pos] * k;
		lazy[pos] += k;
	}
	
	void push (int pos) {
		if (lazy[pos]) {
			add (pos << 1, lazy[pos]);
			add (pos << 1 | 1, lazy[pos]);
			lazy[pos] = 0;
		}
	} 
	
	void update (int pos) {
		sz[pos] = sz[pos << 1] + sz[pos << 1 | 1];
		sum[pos] = sum[pos << 1] + sum[pos << 1 | 1];
	}
	
	void build (int pos, int l, int r) {
		sum[pos] = lazy[pos] = 0;
		if (l == r) {
			sz[pos] = size[id[l]];
			return ;
		}
		int mid = (l + r) >> 1;
		build (pos << 1, l, mid);
		build (pos << 1 | 1, mid + 1, r);
		update (pos);
	}
	
	void modify (int pos, int l, int r, int x, int y, int k) {
		if (x <= l && r <= y) {
			add (pos, k);
			return ;
		}
		push (pos);
		int mid = (l + r) >> 1;
		if (x <= mid) modify (pos << 1, l, mid, x, y, k);
		if (y >= mid + 1) modify (pos << 1 | 1, mid + 1, r, x, y, k);
		update (pos);
	}
	
	int query (int pos, int l, int r, int x, int y) {
		if (x <= l && r <= y) return sum[pos];
		push (pos);
		int mid = (l + r) >> 1, ans = 0;
		if (x <= mid) ans += query (pos << 1, l, mid, x, y);
		if (y >= mid + 1) ans += query (pos << 1 | 1, mid + 1, r, x, y);
		return ans;
	}
} tr2;

void dfs1 (int x, int father) {
	fa[x] = father;
	st[0][x] = father;
	dep[x] = dep[father] + 1;
	size[x] = 1;
	for (int i = 1; i <= 25; i++)
		st[i][x] = st[i - 1][st[i - 1][x]];
	for (auto v : edge[x]) {
		if (v == father) continue;
		dfs1 (v, x);
		size[x] += size[v];
		if (size[son[x]] < size[v]) son[x] = v;
	}
}

void dfs2 (int x, int y) {
	top[x] = y;
	dfn[x] = ++dfntot;
	id[dfntot] = x;
	if (son[x]) dfs2 (son[x], y);
	for (auto v : edge[x]) {
		if (dfn[v]) continue;
		dfs2 (v, v);
	}
}

int lca (int x, int y) {
	if (dep[x] < dep[y]) std::swap(x, y);
	int k = dep[x] - dep[y];
	for (int j = 0; k; j++, k >>= 1) 
		if (k & 1) x = st[j][x];
	if (x == y) return x;
	for (int i = 20; i >= 0; i--) 
		if (st[i][x] != st[i][y]) {
			x = st[i][x];
			y = st[i][y];
		}
	return st[0][x];
}

int depsum[N], asum, adepsum;

void rootupd (int u, int cnt) {
	asum += cnt;
	while (u != 0) {
		tr1.modify (1, 1, n, dfn[top[u]], dfn[u], 0, cnt);
		u = fa[top[u]];
	}
	return ;
}

void subtree (int u, int k) {
	adepsum += k * (depsum[dfn[u] + size[u] - 1] - depsum[dfn[u] - 1]);
	tr2.modify (1, 1, n, dfn[u], dfn[u] + size[u] - 1, k);
	rootupd (fa[u], k * size[u]);
}

int jump (int u, int k) {
	for (int j = 0; k; k >>= 1, j++)
		if (k & 1) u = st[j][u];
	return u;
} 

void work1 (int u, int v) {
	if (u == v) {
		subtree(1, 1);
		return ;
	}
	int k = lca(u, v);
	if (k == v) subtree(1, 1), subtree(jump(u, dep[u] - dep[v] - 1), -1);
	else subtree(v, 1);
		
}

void work2 (int u, int v) {
	int lfs = 0, ris = 0;
	while (top[u] != top[v]) {
		if (dep[top[u]] < dep[top[v]])
			std::swap(u, v), std::swap(lfs, ris);
		tr1.modify (1, 1, n, dfn[top[u]], dfn[u], -1, dfn[u] + 1 + lfs);
		lfs += dfn[top[u]] - dfn[u] + 1;
		adepsum += (depsum[dfn[u]] - depsum[dfn[top[u]] - 1]);
		u = fa[top[u]]; 
	} 
	if (dfn[u] < dfn[v])
		std::swap(u, v), std::swap(lfs, ris);
	adepsum += (depsum[dfn[u]] - depsum[dfn[v] - 1]);
	tr1.modify (1, 1, n, dfn[v], dfn[u], -1, dfn[u] + 1 + lfs);
	tr1.modify (1, 1, n, dfn[v], dfn[v], 0, ris);
	rootupd (fa[v], lfs + ris + dep[u] - dep[v] + 1) ;
}

int getsum (int u) {
	int ans = adepsum;
	while (u != 0) {
		ans = ans - 2 * (tr1.query (1, 1, n, dfn[top[u]], dfn[u]) + tr2.query (1, 1, n, dfn[top[u]], dfn[u]));
		ans = ans + (dfn[u] - dfn[top[u]] + 1) * asum;
		u = fa[top[u]];
	}
	return ans;
}

int main() {
	scanf("%d", &n);
	for (int i = 1, u, v; i < n; i++) {
		scanf("%d%d", &u, &v);
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	dfs1 (1, 0);
	dfs2 (1, 1);
	for (int i = 1; i <= n; i++)
		depsum[i] = depsum[i - 1] + dep[id[i]];
	tr1.build (1, 1, n);
	tr2.build (1, 1, n);
	scanf("%d", &q);
	for (int i = 1, opt, u, v; i <= q; i++) {
		scanf("%d", &opt);
		if (opt == 1) {
			scanf("%d%d", &u, &v);
			work1 (u, v);
		} else if (opt == 2) {
			scanf("%d%d", &u, &v);
			work2 (u, v);
		} else if (opt == 3) {
			scanf("%d", &u);
			printf("%d\n", getsum(u));
		}
	}
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 3ms
memory: 43492kb

input:

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

output:

1
5

result:

ok 2 number(s): "1 5"

Test #2:

score: -100
Wrong Answer
time: 83ms
memory: 46412kb

input:

200
171 114
50 183
28 68
67 152
139 125
67 55
50 98
106 71
46 42
157 165
42 49
113 12
81 145
105 13
38 96
34 156
24 17
21 191
135 54
174 116
177 157
123 71
95 130
135 193
150 129
25 190
96 93
188 173
90 160
86 187
20 132
199 75
59 195
189 24
40 68
163 83
25 13
73 33
59 50
154 19
146 21
151 67
89 69
...

output:

494
400
457
1385
1884
1416
2226
2203
3871
3325
3117
3185
3939
3259
3976
5911
4662
4305
6051
7241
5053
5604
5672
4470
9919
10695
7937
8199
8869
9321
14800
13562
13795
12820
8971
11437
12045
13368
12368
12663
15864
16562
19816
17893
12942
16096
12849
16412
12951
18846
18352
23962
18726
26222
15503
251...

result:

wrong answer 1st numbers differ - expected: '826', found: '494'