为树剖代言,但是 T了
查看原帖
为树剖代言,但是 T了
756660
B612Dusk楼主2023/10/7 09:54

Kruscal 加 树剖,线段树内存第一,二大的值,小常数但是 T\large T 飞了,求调 但我还是要为树剖代言, TT 了全是个人太菜,和树剖无关,资瓷树剖。

AC #1,2,3,4,5, subtask #1,2, T 6,7,8,9,10

#include<bits/stdc++.h>
#define int long long
#define reg register
#define N 300100
const int INF = 0x7ffffffff;
using namespace std;
//char in[1 << 20] ,*ss = in,*tt = in;
//#define getchar() (tt == ss && (tt = (ss = in) + fread(in, 1, 1 << 20,stdin),ss == tt) ? EOF : *ss++)
inline int read()
{
	int x = 0, f = 1;  char ch = getchar();
	while(ch > '9' || ch < '0')
	{
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9')
	{
		x = (x << 3) + (x << 1) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}

int n, m;
int ans, p[N], mixn = INF;

struct Link
{
	int a, b, w;
	bool st;
}link[N];
bool Sort(Link x, Link y) { return x.w < y.w; }

struct edges
{
	int nxt, ver, val;
	#define nxt(p)	edge[p].nxt
	#define ver(p)	edge[p].ver
	#define val(p)	edge[p].val
}edge[N << 1];

int head[N], tot;
inline void add(int a, int b, int c)
{
	edge[++ tot].nxt = head[a];
	edge[tot].val = c;
	edge[tot].ver = b;
	head[a] = tot;
}

int fa[N], sze[N];
int find(int x) { return fa[x] == x ? x : find(fa[x]); }
void merge(int x, int y)
{
	int fx = find(x), fy = find(y);
	if(sze[fx] < sze[fy])	swap(fx, fy);
	fa[fy] = fx;
	sze[fx] += sze[fy];
}

int son[N], dep[N];
void get_son(int x, int Fa)
{
	fa[x] = Fa;
	dep[x] = dep[Fa] + 1;
	sze[x] = 1;
	for(reg int i = head[x];i ; i = nxt(i))
	{
		int y = ver(i);
		if(y == Fa)	 continue;
		get_son(y, x);
		int w = val(i);
		p[y] = w;
		sze[x] += sze[y];
		sze[son[x]] < sze[y] ? son[x] = y : y = y;
	}
}

int dfn[N], vlu[N], cnt, top[N];
void get_chain(int x, int Top)
{
	dfn[x] = ++ cnt;
	vlu[cnt] = p[x];
	top[x] = Top;
	if(!son[x])	 return;
	get_chain(son[x], Top);
	for(reg int i = head[x];i ;i = nxt(i))
	{
		int y = ver(i);
		if(y == fa[x] || y == son[x])	continue;
		get_chain(y, y);
	}
}

struct Sgtree
{
	int l, r, fir, sec;
	#define l(p)	tree[p].l
	#define r(p)	tree[p].r
	#define fir(p)	tree[p].fir
	#define sec(p)	tree[p].sec
}tree[N << 2];

void build(int p, int l, int r)
{
	l(p) = l, r(p) = r;
	if(l == r)
	{
		fir(p) = vlu[l];
		sec(p) = -INF;
		return;
	}
	int mid = l + r >> 1;
	build(p << 1, l , mid);
	build(p << 1 | 1, mid + 1, r);
	fir(p) = max(fir(p << 1), fir(p << 1 | 1));
	if(fir(p << 1) == fir(p << 1 | 1))	sec(p) = max(sec(p << 1), sec(p << 1 | 1));
	else	sec(p) = max( max(sec(p << 1), sec(p << 1 | 1)), min(fir(p << 1), fir(p << 1 | 1)) );
}

//  1 -> fir	0 -> sec
int qry(int p, int l, int r, bool op)
{
	if(l(p) >= l && r(p) <= r)	return (op ? fir(p) : sec(p));
	int mid = l(p) + r(p) >> 1;
	int Fir = -INF, Sec = -INF;
	if(l <= mid)
	{
		int lsf = qry(p << 1, l, r, 1);
		int lsc = qry(p << 1, l, r, 0);
		Fir = lsf, Sec = lsc;
	}
	if(r > mid)
	{
		int rsf = qry(p << 1 | 1, l, r, 1);
		int rsc = qry(p << 1 | 1, l, r, 0);
		if(Fir == -INF)	 Fir = rsf, Sec = rsc;
		else
		{
			if(Fir == rsf)	Sec = max(Sec, rsc);
			else	Sec = max( max(Sec, rsc) , min(Fir, rsf) );
			Fir = max(Fir, rsf);
		}
	}
	return (op ? Fir : Sec);
}

int ch_qry(int x, int y, int op)
{
	int Fir = -INF, Sec = -INF;
	while(top[x] != top[y])
	{
		if(dep[top[x]] < dep[top[y]])	swap(x, y);
		int pf = qry(1, dfn[top[x]], dfn[x], 1);
		int pc = qry(1, dfn[top[x]], dfn[x], 0);
		
		if(Fir == -INF)	  Fir = pf, Sec = pc;
		else
		{
			if(Fir == pf)	Sec = max(Sec, pc);
			else	Sec = max( max(Sec, pc), min(pf, Fir) );
			Fir = max(Fir, pf);
		}
		x = fa[top[x]];
	}
	if(dep[x] > dep[y])	 swap(x, y);
	int pf = qry(1, dfn[x] + 1, dfn[y], 1);
	int pc = qry(1, dfn[x] + 1, dfn[y], 0);
	
	if(Fir == -INF)	Fir = pf, Sec = pc;
	else
	{
		if(Fir == pf)	Sec = max(Sec, pc);
		else	Sec = max( max(Sec, pc), min(pf, Fir) );
		Fir = max(Fir, pf);
	}
	return (op ? Fir : Sec);
}

signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = read(), m = read();
	for(reg int i = 1;i <= m;i = -~i)	link[i] = {read(), read(), read(), 0};
	sort(link + 1, link + m + 1, Sort);
	for(reg int i = 1;i <= n;i = -~i)	fa[i] = i, sze[i] = 1;
	for(reg int i = 1;i <= m;i = -~i)
	{
		int x = link[i].a, y = link[i].b, w = link[i].w;
		int fx = find(x), fy = find(y);
		if(fx == fy)	continue;
		ans += w;
		link[i].st = 1;
		add(x, y, w);
		add(y, x, w);
		merge(fx, fy);
	}
	// ------------------------ Kruscal
	memset(fa, 0, sizeof fa);
	memset(sze, 0, sizeof sze);
	
	get_son(1 , 1);
	get_chain(1, 1);
	build(1, 1, n);

	for(reg int i = 1;i <= m;i = -~i)
	{
		if(link[i].st)	continue;
		int x = link[i].a, y = link[i].b, z = link[i].w;
		int Fir = ch_qry(x, y, 1);
		int Sec = ch_qry(x, y, 0);
		
		if(z != Fir)	mixn = min(mixn, z - Fir);
		else	mixn = min(mixn, z - Sec);
	}
	printf("%lld", ans + mixn);// mixn 存的是比原 ans 大多少
	return 0;
}
2023/10/7 09:54
加载中...