• 洛谷4556 [Vani有约会]雨天的尾巴


    原题链接

    每个点开一个权值线段树,然后用树上差分的方法修改,最后自底向上暴力线段树合并即可。
    不过空间较大,会(MLE),写个内存池就可以了。

    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int N = 1e5 + 10;
    const int M = 6e6 + 10;
    struct dd {
    	int x, y, z;
    };
    dd a[N];
    int fi[N], di[N << 1], ne[N << 1], ro[N], S[M], CO[M], L[M], R[M], de[N], f[N][18], an[N], sta[M], l, ma, gn, SEG, tp;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y)
    {
    	di[++l] = y;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    inline void sw(int &x, int &y)
    {
    	int z = x;
    	x = y;
    	y = z;
    }
    inline int maxn(int x, int y){ return x > y ? x : y; }
    void dfs(int x)
    {
    	int i, y;
    	for (i = 1; i <= gn; i++)
    		f[x][i] = f[f[x][i - 1]][i - 1];
    	for (i = fi[x]; i; i = ne[i])
    		if (!de[y = di[i]])
    		{
    			de[y] = de[x] + 1;
    			f[y][0] = x;
    			dfs(y);
    		}
    }
    int lca(int x, int y)
    {
    	int i;
    	if (de[x] > de[y])
    		sw(x, y);
    	for (i = gn; ~i; i--)
    		if (de[f[y][i]] >= de[x])
    			y = f[y][i];
    	if (!(x ^ y))
    		return x;
    	for (i = gn; ~i; i--)
    		if (f[x][i] ^ f[y][i])
    		{
    			x = f[x][i];
    			y = f[y][i];
    		}
    	return f[x][0];
    }
    void pp(int r)
    {
    	int lx = L[r], rx = R[r];
    	if (S[lx] < S[rx])
    	{
    		S[r] = S[rx];
    		CO[r] = CO[rx];
    	}
    	else
    	{
    		S[r] = S[lx];
    		CO[r] = CO[lx];
    	}
    }
    inline void rec(int x){ sta[++tp] = x; }
    inline int NEW(){ return tp ? sta[tp--] : ++SEG; }
    void mdf(int &r, int x, int y, int k, int v)
    {
    	if (!r)
    		r = ++SEG;
    	if (!(x ^ y))
    	{
    		S[r] += v;
    		S[r] > 0 ? CO[r] = x : CO[r] = 0;
    		return;
    	}
    	int mid = (x + y) >> 1;
    	k <= mid ? mdf(L[r], x, mid, k, v) : mdf(R[r], mid + 1, y, k, v);
    	pp(r);
    }
    int merge(int x, int y, int r_1, int r_2)
    {
    	if (!r_1)
    		return r_2;
    	if (!r_2)
    		return r_1;
    	int r = NEW();
    	if (!(x ^ y))
    	{
    		S[r] = S[r_1] + S[r_2];
    		S[r] > 0 ? CO[r] = x : CO[r] = 0;
    		return r;
    	}
    	int mid = (x + y) >> 1;
    	L[r] = merge(x, mid, L[r_1], L[r_2]);
    	R[r] = merge(mid + 1, y, R[r_1], R[r_2]);
    	pp(r);
    	rec(r_1);
    	rec(r_2);
    	return r;
    }
    void UPD(int x)
    {
    	int i, y;
    	for (i = fi[x]; i; i = ne[i])
    		if ((y = di[i]) ^ f[x][0])
    		{
    			UPD(y);
    			ro[x] = merge(1, ma, ro[x], ro[y]);
    		}
    	an[x] = CO[ro[x]];
    }
    int main()
    {
    	int i, n, m, x, y, LCA;
    	n = re();
    	m = re();
    	gn = log2(n);
    	for (i = 1; i < n; i++)
    	{
    		x = re();
    		y = re();
    		add(x, y);
    		add(y, x);
    	}
    	de[1] = 1;
    	dfs(1);
    	for (i = 1; i <= m; i++)
    	{
    		a[i].x = re();
    		a[i].y = re();
    		a[i].z = re();
    		ma = maxn(ma, a[i].z);
    	}
    	for (i = 1; i <= m; i++)
    	{
    		LCA = lca(a[i].x, a[i].y);
    		mdf(ro[a[i].x], 1, ma, a[i].z, 1);
    		mdf(ro[a[i].y], 1, ma, a[i].z, 1);
    		mdf(ro[LCA], 1, ma, a[i].z, -1);
    		if (LCA ^ 1)
    			mdf(ro[f[LCA][0]], 1, ma, a[i].z, -1);
    	}
    	UPD(1);
    	for (i = 1; i <= n; i++)
    		printf("%d
    ", an[i]);
    	return 0;
    }
    
  • 相关阅读:
    Eclipse 插件Maven在使用 add dependency,找不到包,解决办法
    SimpleDateFormat是线程不安全的,切忌切忌!
    JNative 传递参数bug
    oracle存储过程递归调用
    oracle调用DLL
    telnet和Netstat使用
    notepad++搭配dev配置运行C++
    ubuntu第一次安装登陆密码不正确问题
    区分形参和实参
    爬虫2
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9897756.html
Copyright © 2020-2023  润新知