1 条题解

  • 1
    @ 2024-11-3 17:48:01

    相信开这道题的神犇一定会树剖,但是树剖一般是维护的点权,所以对于边权,我们将该边的边权存到这条边所连的两个点中更深的那个点就好了。

    注意边界!!!

    我用的珂朵莉树,大概 O(nlogn)O(n2logn) O (n \log {n}) \to O (n ^ 2 log {n}) ,实测能过。

    code:

    # include <bits/stdc++.h>
    # define int long long
    using namespace std;
    struct node
    {
    	long long l, r;
    	mutable long long v;
    	node (long long l, long long r = 0, long long v = 0) : l (l), r (r), v (v) {}
    	bool operator < (const node &other) const { return l < other.l; }
    };
    set <node> tree;
    inline set<node> :: iterator split (register long long pos)
    {
    	set <node> :: iterator it = tree.lower_bound (node (pos));
    	if (it != tree.end () and it -> l == pos) return it; it --;
    	if (it -> r < pos) return tree.end();
    	register long long l = it -> l;
    	register long long r = it -> r;
    	register long long v = it -> v;
    	tree.erase (it), tree.insert (node (l, pos - 1, v));
    	return tree.insert (node (pos, r, v)).first;
    }
    inline void cover (int l, int r, int x)
    {
    	set <node> :: iterator rr = split (r + 1), ll = split (l);
    	tree.erase (ll, rr); tree.insert (node (l, r, x)); return;
    }
    inline void add (int l, int r, int x)
    {
    //	cout << l << ' ' << r << endl;
    	set <node> :: iterator rr = split (r + 1), ll = split (l);
    	for (auto it = ll; it != rr; it ++) it -> v += x;
    }
    int find (int l, int r)
    {
    	set <node> :: iterator rr = split (r + 1);
    	set <node> :: iterator ll = split (l);
    	int ret = 0;
    	for (auto it = ll; it != rr; it ++)
    	{
    		ret = max (ret, it -> v);
    	}
    	return ret;
    }
    int depth[200012], fa[200012], s[200012], son[200012];
    int pos, id[200012], top[200012]; vector <int> e[200012];
    int w[200012], num[200012];
    
    int n;
    
    inline void dfs1 (int u, int father,int dep){
    	depth[u] = dep;
    	fa[u] = father;
    	s[u] = 1;
    	int ch = -1;
    	for(unsigned int i = 0; i < e[u].size (); i ++)
    	{
    		int v = e[u][i];
    		if (v == father)
    		{
    			continue;
    		}
    		dfs1 (v, u, dep + 1);
    		s[u] += s[v];
    		if (s[v] > ch)
    		{
    			son[u] = v;
    			ch = s[v];
    		}
    	}
    }
    
    inline void dfs2 (int u, int father)
    {
    	++ pos;
    	id[u] = pos;
    	num[pos] = w[u];
    	top[u] = father;
    	if (not son[u])
    	{
    		return;
    	}
    	dfs2 (son[u], father);
    	for(unsigned int i = 0; i < e[u].size (); i ++)
    	{
    		int v = e[u][i];
    		if (v == fa[u] or v == son[u])
    		{
    			continue;
    		}
    		dfs2 (v, v);
    	}
    }
    
    void amend (int u, int v, int x)
    {
    	while (top[u] != top[v])
    	{
    		if (depth[top[u]] < depth[top[v]])
    		{
    			swap (u, v);
    		}
    //		cout << u << ' ' << v << endl;
    		add (id[top[u]], id[u], x);
    		u = fa[top[u]];
    	}
    	if (depth[u] > depth[v]) swap (u, v);
    	if (u == v) return;
    //	cout << id[u] + 1 << ' ' << id[v] << endl;
    	add (id[u] + 1, id[v], x);
    }
    
    void change (int u, int v, int x)
    {
    	while (top[u] != top[v])
    	{
    		if (depth[top[u]] < depth[top[v]])
    		{
    			swap (u, v);
    		}
    		cover (id[top[u]], id[u], x);
    		u = fa[top[u]];
    	}
    	if (u == v) return;
    	if (depth[u] > depth[v]) swap (u, v);
    	cover (id[u] + 1, id[v], x);
    }
    
    long long mx (int u, int v)
    {
    	int ret = 0;
    	while (top[u] != top[v])
    	{
    		if (depth[top[u]] < depth[top[v]])
    		{
    			swap (u, v);
    		}
    		ret = max (ret, find (id[top[u]], id[u]));
    		u = fa[top[u]];
    	}
    	if (depth[u] > depth[v]) swap (u, v);
    	ret = max (ret, find (id[u] + 1, id[v]));
    	return ret;
    }
    struct path
    {
    	int u, v, w;
    }a[200012];
    signed main ()
    {
    	ios :: sync_with_stdio (0);
    	cin.tie (0), cout.tie (0);
    	cin >> n;
    	for (int i = 1; i < n; i ++)
    	{
    		cin >> a[i].u >> a[i].v >> a[i].w;
    		e[a[i].u].push_back (a[i].v);
    		e[a[i].v].push_back (a[i].u);
    	}
    	dfs1 (1, 0, 0);
    	dfs2 (1, 0);
    	for (int i = 1; i <= n; i ++)
    	{
    		int u = a[i].u, v = a[i].v, weight = a[i].w;
    		if (fa[v] == u)
    		{
    			w[v] = weight;
    			num[id[v]] = w[v];
    		}
    		else
    		{
    			w[u] = weight;
    			num[id[u]] = w[u];
    		}
    	}
    	tree.insert (node (1, n, 0));
    	for (int i = 1; i <= n; i ++) cover (i, i, num[i]);
    //	cout << id[2] << ' ' << num[id[2]] << endl;
    	while (true)
    	{
    		string op;
    		cin >> op;
    		if (op == "Stop") break;
    		if (op == "Cover")
    		{
    			int u, v, x;
    			cin >> u >> v >> x;
    			if (u == v) continue;
    			change (u, v, x);
    		}
    		else if (op == "Change")
    		{
    			int k, x;
    			cin >> k >> x;
    			int u = a[k].u;
    			int v = a[k].v;
    			change (u, v, x);
    		}
    		else if (op == "Add")
    		{
    			int u, v, x;
    			cin >> u >> v >> x;
    			if (u == v) continue;
    			amend (u, v, x);
    		}
    		else
    		{
    			int u, v;
    			cin >> u >> v;
    			cout << mx (u, v) << "\n";
    		}
    	}
    }
    

    信息

    ID
    8342
    时间
    1000ms
    内存
    128MiB
    难度
    5
    标签
    递交数
    3
    已通过
    3
    上传者