社区讨论

求问常数

学术版参与者 2已保存回复 8

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
7 条
当前快照
1 份
快照标识符
@mi8ujhyu
此快照首次捕获于
2025/11/21 20:38
4 个月前
此快照最后确认于
2025/11/21 21:20
4 个月前
查看原帖
猎奇分块做法,时间复杂度 O(nn)O(n \sqrt n)。求问为什么在 At 和 自己学校的网站上都会 TLE。自己学校网站上极限数据要跑 4s。是常数太大了还是时间复杂度确实有问题,虚心请教!
代码CPP
#include <bits/stdc++.h>
#define ll long long
#define rint register int
using namespace std;

const int maxn = 2e5 + 5, maxb = 500;

int n;

ll f[maxn], ans[maxn];

unordered_map <int, ll> key[maxn];

// 以 i 为根 j 子树中小于 j 的个数 

int head[maxn], ecnt;

struct Edge {
	int nxt, to;
} edge[maxn << 1];

inline void add(int from, int to) {
	edge[++ecnt] = {head[from], to};
	head[from] = ecnt;
	return;
}

struct chunking {
	int block, a[maxn], b[maxn], pos[maxn], l[maxb], r[maxb];
	
	void init() {
		block = sqrt(n);
		for(rint i = 1; i <= n; i++) {
			pos[i] = (i + block - 1) / block;
			b[i] = a[i];
			if(pos[i] != pos[i - 1]) l[pos[i]] = i;
			r[pos[i]] = max(r[pos[i]], i);
		}
		for(rint i = 1; i <= pos[n]; i++) sort(b + l[i], b + r[i] + 1);
		return;
	}
	
	ll qry(int x, int y, int k) {
		ll res = 0;
		if(pos[x] == pos[y]) {
			for(rint i = x; i <= y; i++) res += (a[i] < k);
			return res;
		}
		for(rint i = x; pos[i] == pos[x]; i++) res += (a[i] < k);
		for(rint i = y; pos[i] == pos[y]; i--) res += (a[i] < k);
		for(rint i = pos[x] + 1; i <= pos[y] - 1; i++)
			if(b[l[i]] < k) res += lower_bound(b + l[i], b + r[i] + 1, k) - (b + l[i]);
		return res;
	}
} ch;

struct tree_cutting {
	int tim, siz[maxn], dfn[maxn];
	
	void dfs(int x, int fa) {
		siz[x] = 1, dfn[x] = ++tim;
		ch.a[dfn[x]] = x;
		for(rint i = head[x]; i; i = edge[i].nxt) {
			int to = edge[i].to;
			if(to == fa) continue;
			dfs(to, x);
			siz[x] += siz[to];
		}
		return;
	}
	
	ll qry_sub(int x, int k) { return ch.qry(dfn[x], dfn[x] + siz[x] - 1, k); }
} tc;

struct dynamic_programing {
	void dfs1(int x, int fa) {
		ll sum = 0;
		for(rint i = head[x]; i; i = edge[i].nxt) {
			int to = edge[i].to;
			if(to == fa) continue;
			key[x][to] = tc.qry_sub(to, to);
			sum += tc.qry_sub(to, fa);
			dfs1(to, x);
			f[x] += f[to] + key[x][to];
		}
		if(fa) key[x][fa] = fa - 1 - sum - (x < fa);
		return;
	}
	
	void dfs2(int x, int fa) {
		ans[x] = f[x] + x - 1;
		for(rint i = head[x]; i; i = edge[i].nxt) {
			int to = edge[i].to;
			if(to == fa) continue;
			ll f_x = f[x], f_to = f[to];
			f[x] -= f[to] + key[x][to];
			f[to] += f[x] + key[to][x];
			dfs2(to, x);
			f[x] = f_x, f[to] = f_to;
		}
		return;
	}
} dp;

int read() {
	int k = 0, f = 1;
	char c = getchar();
	while(c < '0' || '9' < c) f = (c == '-') ? -1 : 1, c = getchar();
	while('0' <= c && c <= '9') k = k * 10 + c - '0', c = getchar();
	return k * f;
}

void write(ll x) {
	if(x < 0) putchar('-'), x = -x;
	if(x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

int main() {
	n = read();
	int u, v;
	for(rint i = 1; i < n; i++) {
		u = read(), v = read();
		add(u, v), add(v, u);
	}
	tc.dfs(1, 0), ch.init();
	dp.dfs1(1, 0), dp.dfs2(1, 0);
	for(rint i = 1; i <= n; i++) write(ans[i]), putchar(' ');
	return 0;
}

回复

8 条回复,欢迎继续交流。

正在加载回复...