TLE on #29,有注释,翻了前面的帖子不知道哪里错了
  • 板块CF487E Tourists
  • 楼主SJZ2010
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/7/2 17:21
  • 上次更新2024/7/2 20:19:35
查看原帖
TLE on #29,有注释,翻了前面的帖子不知道哪里错了
809729
SJZ2010楼主2024/7/2 17:21

建圆方树再树链剖分,线段树单点修改区间求 min,应该没哪里错吧,怎么回事呢?

submission

#include <bits/stdc++.h>
using namespace std;

using LL = __int128; // 缺省源,可以忽略
using ll = long long;
using ldb = long double;
using vi = vector < int >;
#define ve vector < edge >
#define pb(x) emplace_back(x)
#define lowbit(x) ((x) & -(x))
#define me(a, b) memset(a, b, sizeof(a));
#define L(i, j, k) for (int i = j; i <= (k); i++)
#define R(i, j, k) for (int i = j; i >= (k); i--)
#define debug cerr << __FILE__ << ": " << __LINE__ << '\n';
#define qio() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
namespace io { // 快读模板,可以忽略
	char buf[1 << 21], *p1 = buf, *p2 = buf;
	#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
	int read() {
		int res(0), f(1);
		char ch(getchar());
		while (ch < '0' || ch > '9') {
			if (ch == '-')
				f = -1;
			ch = getchar();
		}
		while (ch >= '0' && ch <= '9') {
			res = res * 10 + (ch ^ '0');
			ch = getchar();
		}
		return res * f;
	}
} using io::read;

template < class T >
ostream& operator << (ostream& out, vector < T > v) {
	out << '[';
	if (!v.empty()) {
		L(i, 0, v.size() - 2)
			out << v[i] << ',';
		out << v[v.size() - 1];
	}
	return out << ']';
}
namespace Dbg { // 用来 Debug 的部分,可以忽略
	template < class T >
	void dbg(char *f, T t) {
		cerr << f << '=' << t << endl;
	}
	template < class T, class ...Ar >
	void dbg(char *f, T x, Ar... y) {
		while (*f != ',')
			cerr << *f++;
		cerr << '=' << x << ',';
		dbg(f + 1, y...);
	}
}
#define gdb(...) cerr << "gdb in line " <<__LINE__ << ": ", Dbg::dbg((char*)#__VA_ARGS__,__VA_ARGS__);

const int N = 1e5 + 5; // Adjust
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;

int n, m, q, w[N];
vi G[N], T[N << 1];
multiset < int > bw[N];

namespace trjn {
	int dfn[N], low[N], dfc, cnt;
	int stk[N], top;

	void rebuild(int u) { // 建圆方树
		dfn[u] = low[u] = ++dfc;
		stk[++top] = u;

		for (int v : G[u])
			if (!dfn[v]) {
				rebuild(v);
				low[u] = min(low[u], low[v]);
				if (low[v] == dfn[u]) {
					++cnt;
					for (int x = 0; x != v; --top) {
						T[x = stk[top]].pb(cnt);
						T[cnt].pb(x);
					}
					T[cnt].pb(u);
					T[u].pb(cnt);
				}
			} else
				low[u] = min(low[u], dfn[v]);
	}
}
namespace hld {
	int fa[N << 1], dep[N << 1], siz[N << 1], hs[N << 1], top[N << 1], dfn[N << 1];
	// Don't forget to time 2!
	int dfc;

	void dfs1(int u, int f) { // 剖
		fa[u] = f;
		dep[u] = dep[f] + 1;
		siz[u] = 1;

		for (int v : T[u])
			if (v != f) {
				dfs1(v, u);
				if (siz[v] > siz[hs[u]])
					hs[u] = v;
			}
	}
	void dfs2(int u, int t) {
		dfn[u] = ++dfc;
		top[u] = t;

		if (!hs[u])
			return;
		dfs2(hs[u], t);

		for (int v : T[u])
			if (v != fa[u] && v != hs[u])
				dfs2(v, v);
	}

	struct sgt { // 树剖的线段树
		int dt[N << 3];

		sgt() {
			me(dt, 0x3f);
		}

		#define ls(u) (u << 1)
		#define rs(u) (u << 1 | 1)
		#define pushup(u) dt[u] = min(dt[ls(u)], dt[rs(u)])

		void modify(int s, int t, int k, int u, int d) {
//			gdb(s, t, k, u, d);
			if (s == t) {
				dt[u] = d;
				return;
			}
			int mid = (s + t) >> 1;
			if (mid >= k)
				modify(s, mid, k, ls(u), d);
			else
				modify(mid + 1, t, k, rs(u), d);
			pushup(u);
		}
		int query(int s, int t, int l, int r, int u) {
			if (l <= s && t <= r)
				return dt[u];
			int mid = (s + t) >> 1, res = inf;
			if (mid >= l)
				res = query(s, mid, l, r, ls(u));
			if (mid < r)
				res = min(res, query(mid + 1, t, l, r, rs(u)));
			return res;
		}
	} tr;

	void init() {
		L(i, 2, n)
			bw[fa[i] - n].insert(w[i]);
		L(i, 1, n)
			tr.modify(1, dfc, dfn[i], 1, w[i]);
		L(i, n + 1, dfc)
			tr.modify(1, dfc, dfn[i], 1, *bw[i - n].begin());
	}

	void modify(int u, int nw) {
		if (!fa[u]) { // root 的特判,不给 ta 改父亲(fa[1] = 0)
			tr.modify(1, dfc, dfn[u], 1, w[u] = nw);
			return;
		}
		
		bw[fa[u] - n].erase(w[u]);
		bw[fa[u] - n].insert(w[u] = nw);
		tr.modify(1, dfc, dfn[u], 1, nw);
		tr.modify(1, dfc, dfn[fa[u]], 1, *bw[fa[u] - n].begin());
	}
	int query(int u, int v) {
		int res = inf;

		while (top[u] != top[v]) {
			if (dep[top[u]] < dep[top[v]])
				swap(u, v);
			res = min(res, tr.query(1, dfc, dfn[top[u]], dfn[u], 1));
//			gdb(dfn[u], dfn[top[u]], res);
			u = fa[top[u]];
		}

		if (dep[u] > dep[v])
			swap(u, v);
		res = min(res, tr.query(1, dfc, dfn[u], dfn[v], 1));

		if (u > n) // u is a block vertex
			res = min(res, w[fa[u]]);

		return res;
	}
}

int main() {
	qio();
	cin >> n >> m >> q;
	trjn::cnt = n;
	L(i, 1, n)
		cin >> w[i];

	int u, v;
	while (m--) {
		cin >> u >> v;
		G[u].pb(v), G[v].pb(u);
	}

	trjn::rebuild(1); // 建圆方树
	hld::dep[1] = 1; // 树剖
	hld::dfs1(1, 0);
	hld::dfs2(1, 1);
	hld::init(); // 预处理树剖的线段树与 multiset

	char opt;
	while (q--) {
		cin >> opt >> u >> v;
		if (opt == 'A') {
			printf("%d\n", hld::query(u, v));
		} else {
			hld::modify(u, v);
		}
	}

	return 0;
}
2024/7/2 17:21
加载中...