社区讨论

求卡常,95pts TLE on #6

P4775[NOI2018] 情报中心参与者 4已保存回复 4

讨论操作

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

当前回复
4 条
当前快照
1 份
快照标识符
@m34h9yu3
此快照首次捕获于
2024/11/05 21:20
去年
此快照最后确认于
2025/11/04 15:16
4 个月前
查看原帖
CPP
#include <bits/stdc++.h>

using namespace std;
bool debug = false, debug2 = false;

#define int long long

inline int read()
{
    int x=0,f=1;
    char ch;
    while(ch>'9'||ch<'0')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while('0'<=ch&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
                        
inline void write(int x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>=10)write(x/10);
    putchar(x%10+'0');
}

const int N = 5e4 + 5, M = 2e5 + 5;
const int SZ = 1e7;
const int inf = 0x3f3f3f3f3f3f3f3f;


int n, m;
struct Edge {
	int to, val;
	Edge(int t = 0, int v = 0) {
		to = t, val = v;
	}
};
vector<Edge> e[N];


int dfn[N], cur = 0;
int st[20][N], pw[20], lg[N] = {};
int d[N], dep[N] = {};
int fa[16][N];

void dfs(int x, int pr, int dth) {
	dep[x] = dep[pr] + 1;
	dfn[x] = ++cur;
	d[x] = dth;
	st[0][dfn[x]] = pr;
	fa[0][x] = pr;
	for (int i = 1; i < 16; i++)
		fa[i][x] = fa[i - 1][fa[i - 1][x]];
	for (auto i: e[x])
		if (i.to != pr)
			dfs(i.to, x, dth + i.val);
}
int sml(int x, int y) {
	if (dfn[x] < dfn[y])
		return x;
	return y;
}
void init_ST() {
	pw[0] = 1;
	for (int i = 1; i < 20; i++)
		pw[i] = pw[i - 1] * 2;
	for (int i = 2; i <= n; i++)
		lg[i] = lg[i / 2] + 1;
	for (int i = 1; i < 20; i++)
		for (int j = 1; j + pw[i] - 1 <= n; j++)
			st[i][j] = sml(st[i - 1][j], st[i - 1][j + pw[i - 1]]);
}
inline int lca(int x, int y) {
	if (x == y)
		return x;
	x = dfn[x], y = dfn[y];
	if (x > y)
		swap(x, y);
	int s = lg[y - x];
	return sml(st[s][x + 1], st[s][y - pw[s] + 1]);
}
inline int up(int x, int t) {
	for (int i = 15; i >= 0; i--)
		if (dep[fa[i][x]] > dep[t])
			x = fa[i][x];
	return x;
}

inline int dist(int x, int y) {
	int lc = lca(x, y);
	return d[x] + d[y] - 2 * d[lc];
}

struct Path {
	int u, v, w;
	int C;
	void getC() {
		C = dist(u, v) - 2 * w;
	}
} p[M];
typedef pair<int, int> pii;

int cst[M];

inline int len(int id1, int id2) {
	if (id1 == -1 || id2 == -1)
		return ~inf;
	int v1 = p[id1].v, v2 = p[id2].v;
	return cst[id1] + cst[id2] + dist(v1, v2);
}
inline int len(pii x) {
	return len(x.first, x.second);
}

inline bool chk(int id1, int id2) {
	return min(id1, id2) + m != max(id1, id2);
}
inline pii operator+(pii a, pii b) {
	pii ret = a;
	if ((ret.first == -1 && ret.second == -1) || len(ret) < len(b))
		ret = b;
	if (chk(a.first, b.first) && len(ret) < len(a.first, b.first))
		ret = make_pair(a.first, b.first);
	if (chk(a.first, b.second) && len(ret) < len(a.first, b.second))
		ret = make_pair(a.first, b.second);
	if (chk(a.second, b.first) && len(ret) < len(a.second, b.first))
		ret = make_pair(a.second, b.first);
	if (chk(a.second, b.second) && len(ret) < len(a.second, b.second))
		ret = make_pair(a.second, b.second);
	return ret;
}
inline pii operator*(pii a, pii b) {
	pii ret = make_pair(-1, -1);
	if (chk(a.first, b.first) && len(ret) < len(a.first, b.first))
		ret = make_pair(a.first, b.first);
	if (chk(a.first, b.second) && len(ret) < len(a.first, b.second))
		ret = make_pair(a.first, b.second);
	if (chk(a.second, b.first) && len(ret) < len(a.second, b.first))
		ret = make_pair(a.second, b.first);
	if (chk(a.second, b.second) && len(ret) < len(a.second, b.second))
		ret = make_pair(a.second, b.second);
	return ret;
}
struct SegmentTree {
	int n;
	int rt[N];
	int ls[SZ], rs[SZ];
	pii val[SZ]; //保存两条最优路径的编号 
	
	void pushup(int x) {
		if (!ls[x] || !rs[x])
			val[x] = val[ls[x] + rs[x]];
		else
			val[x] = val[ls[x]] + val[rs[x]];
	}
	void mdf(int &x, int lx, int rx, int p, int v) {
		if (x == 0) {
			x = ++n;
			ls[x] = rs[x] = 0;
			val[x] = make_pair(-1, -1);
		}
		if (lx + 1 == rx) {
			if (v == -1)
				val[x] = make_pair(-1, -1);
			else
				val[x] = make_pair(lx, -1);
//			if (debug)
//				printf("%d:%d %d\n", x, val[x].first, val[x].second);
			return ;
		}
		int m = (lx + rx) / 2;
		if (p < m)
			mdf(ls[x], lx, m, p, v);
		else
			mdf(rs[x], m, rx, p, v);
		
		pushup(x);
//		if (debug) {
//			printf("%d:%d %d\n", x, val[x].first, val[x].second);
//			printf("%d, %d %d\n", x, ls[x], rs[x]);
//		}
	}
	int mrg(int L, int R, int lx, int rx) {
		if (L == 0 || R == 0)
			return L + R;
		if (lx + 1 == rx) {
			val[L] = val[L] + val[R];
			return L;
		}
		int m = (lx + rx) / 2;
		ls[L] = mrg(ls[L], ls[R], lx, m);
		rs[L] = mrg(rs[L], rs[R], m, rx);
		pushup(L);
		return L;
	}
} sgt;

vector<int> tag[N];
int ans;

inline void clear_vec(vector<int> &v) {
	vector<int> tmp;
	swap(v, tmp);
}
void clear_all() {
	ans = -inf;
	for (int i = 1; i <= sgt.n; i++) {
		sgt.val[i] = make_pair(-1, -1);
		sgt.ls[i] = sgt.rs[i] = 0;
	}
	sgt.val[0] = make_pair(-1, -1);
	sgt.n = 0;
	for (int i = 1; i <= n; i++) {
		sgt.rt[i] = 0;
		clear_vec(tag[i]);
		e[i].clear();
	}
	cur = 0;
}

void srh(int x, int pr) {
	if (sgt.val[sgt.rt[x]].first != -1 && sgt.val[sgt.rt[x]].second != -1)
		ans = max(ans, len(sgt.val[sgt.rt[x]]) - 2 * d[x]);
	for (auto i: e[x]) {
		if (i.to == pr)
			continue;
		srh(i.to, x);
		
		
		pii tmp = sgt.val[sgt.rt[x]] * sgt.val[sgt.rt[i.to]];
		if (tmp.first != -1 && tmp.second != -1)
			ans = max(ans, len(tmp) - 2 * d[x]);
		sgt.rt[x] = sgt.mrg(sgt.rt[x], sgt.rt[i.to], 1, 2 * m + 1);	
	}
	
	for (auto i: tag[x]) {
		sgt.mdf(sgt.rt[x], 1, 2 * m + 1, i, -1);
	}
}
void slv() {
	n = read();
	clear_all();
	for (int i = 1, u, v, w; i < n; i++) {
		u = read();
		v = read();
		w = read();
		e[u].push_back(Edge(v, w));
		e[v].push_back(Edge(u, w));
	}
	dfs(1, 0, 0);
	init_ST();
 
	m = read();
	for (int i = 1; i <= m; i++) {
		p[i].u = read();
		p[i].v = read();
		p[i].w = read();
		if (p[i].u == p[i].v)
			continue;
			
		p[m + i] = p[i];
		swap(p[m + i].u, p[m + i].v);
		p[i].getC();
		p[m + i].getC();
		
		cst[i] = p[i].C + d[p[i].u];
		cst[m + i] = p[m + i].C + d[p[m + i].u];
		
		if (lca(p[i].u, p[i].v) != p[i].u) {
			sgt.mdf(sgt.rt[p[i].u], 1, 2 * m + 1, i, 1);
			tag[up(p[i].u, lca(p[i].u, p[i].v))].push_back(i);
		}
		
		if (lca(p[m + i].u, p[m + i].v) != p[m + i].u) {
			sgt.mdf(sgt.rt[p[m + i].u], 1, 2 * m + 1, m + i, 1);
			tag[up(p[m + i].u, lca(p[m + i].u, p[m + i].v))].push_back(m + i);
		}
	}
	
	srh(1, 0);
	if (ans == -inf) {
		putchar('F');
		putchar('\n');
	}
	else {
		write(ans / 2);
		putchar('\n');
	}
}

signed main() {
	int T;
	cin >> T;
	for (int i = 1; i <= T; i++) {
		slv();
	}	
	return 0;
}

回复

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

正在加载回复...