求条,样例没过,马蜂良好
查看原帖
求条,样例没过,马蜂良好
838570
Double_Sheep楼主2024/5/15 22:14

rt. 代码加了注释.

样例 #2 挂了,调了很久了qwq。

(ps:tarjan / dfs / 线段树应该都没问题 ,但也不保证()

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n,m,q,sum,w[N],head[N],tot,tot2,sz[N],head2[N],tim[N];
int son[N],Top[N],dep[N],dfn[N],low[N],cnt,fa[N],W[N];
//一些正常的 tarjan & 树剖的数组
stack<int> s;
multiset<int> V[N]; //存儿子最小值
struct edge {int v,nxt;}e[N << 1],g[N << 1];
//e是输入的图,g是圆方树
struct tree {int l,r,v;}t[N << 2];
void add(int u,int v) {
	e[++tot] = edge {v,head[u]};
	head[u] = tot;
}
void add2(int u,int v) {
	g[++tot2] = edge {v,head2[u]};
	head2[u] = tot2;
} //两个建图,写的可能有点繁琐QAQ
void tarjan(int u,int f) {
	dfn[u] = low[u] = ++sum; s.push(u);
	for(int i = head[u];i;i = e[i].nxt) {
		int v = e[i].v; if(v == f) continue;
		if(!dfn[v]) {
			tarjan(v,u);
			low[u] = min(low[u],low[v]);
			if(low[v] >= dfn[u]) {
				w[++cnt] = w[u]; int x = 0;
				add2(cnt,u),add2(u,cnt);
				do
					x = s.top(),add2(cnt,x),add2(x,cnt),s.pop();
				while(x != v);
			}
		} else low[u] = min(low[u],dfn[v]);
	}
} // ---tarjan---
void pushup(int p) {
	t[p].v = min(t[p << 1].v,t[p << 1 | 1].v);
}
void build(int p,int l,int r) {
	t[p].l = l,t[p].r = r;
	if(l == r) {t[p].v = W[l]; return;}
	int mid = (l + r) >> 1;
	build(p << 1,l,mid);
	build(p << 1 | 1,mid + 1,r);
	pushup(p);
}
void modify(int p,int qp,int v) {
	if(t[p].l == t[p].r) {
		t[p].v = v; return;
	} int mid = (t[p].l + t[p].r) >> 1;
	if(qp <= mid) modify(p << 1,qp,v);
	else modify(p << 1 | 1,qp,v);
	pushup(p);
}
int query(int p,int ql,int qr) {
	if(ql <= t[p].l && t[p].r <= qr)
		return t[p].v;
	int mid = (t[p].l + t[p].r) >> 1,ans = 1e9;
	if(ql <= mid) ans = min(ans,query(p << 1,ql,mid));
	if(mid < qr) ans = min(ans,query(p << 1 | 1,mid + 1,qr));
	return ans;
} // ---segment tree---
void dfs(int u,int f) {
	fa[u] = f,dep[u] = dep[f] + 1,sz[u] = 1;
	for(int i = head2[u];i;i = g[i].nxt) {
		int v = g[i].v; if(v == f) continue;
		dfs(v,u); sz[u] += sz[v];
		if(sz[son[u]] < sz[v]) son[u] = v;
	}
}
void dfs2(int u,int top) {
	Top[u] = top,tim[u] = ++sum; //sum为时间戳
	if(son[u]) dfs2(son[u],top);
	for(int i = head2[u];i;i = g[i].nxt) {
		int v = g[i].v;
		if(v != son[u] && v != fa[u]) dfs2(v,v);
	}
}
void init() {
	for(int i = 1;i <= n;i++)
		W[tim[i]] = w[i];
	for(int i = n + 1;i <= cnt;i++) {
		for(int j = head2[i];j;j = g[j].nxt) {
			int v = g[j].v;
			if(v != fa[i]) V[i].insert(w[v]);
		}
		if(V[i].empty()) w[i] = 1e9;
		else w[i] = *V[i].begin();
		W[tim[i]] = w[i];
	} build(1,1,cnt);
}
void update(int u,int v) {
	if(fa[u]) { //修改父亲权值
		V[fa[u]].erase(V[fa[u]].find(w[u]));
		V[fa[u]].insert(v);
		w[fa[u]] = *V[fa[u]].begin();
		modify(1,tim[fa[u]],w[fa[u]]);
	}
	w[u] = v; modify(1,tim[u],v);
}
int ask(int u,int v) {
	int ans = 1e9;
	while(Top[u] != Top[v]) {
		if(dep[Top[u]] < dep[Top[v]]) swap(u,v);
		ans = min(ans,query(1,tim[Top[u]],tim[u]));
		u = fa[Top[u]];
	}
	if(dep[u] > dep[v]) swap(u,v);
	ans = min(ans,query(1,tim[u],tim[v]));
	if(u > n) ans = min(ans,w[fa[u]]); //方点,要处理父亲
	return ans;
} // ---树链剖分---
int main() {
	scanf("%d%d%d",&n,&m,&q); cnt = n;
	for(int i = 1;i <= n;i++)
		scanf("%d",&w[i]);
	for(int i = 1;i <= m;i++) {
		int u,v; scanf("%d%d",&u,&v);
		add(u,v),add(v,u);
	}
	for(int i = 1;i <= n;i++)
		if(!dfn[i]) tarjan(i,0);
	sum = 0; dfs(1,0),dfs2(1,1),init();
	for(int i = 1;i <= q;i++) {
		string s; int x,y;
		cin >> s; scanf("%d%d",&x,&y);
		if(s[0] == 'C') update(x,y);
		else printf("%d\n",ask(x,y));
	}
	return 0;
}
2024/5/15 22:14
加载中...