zoukankan      html  css  js  c++  java
  • CSAcademy Round 10 Yury's Tree(有根树点分树或kruskal重构树)

    https://csacademy.com/contest/archive/task/yurys-tree

    https://csacademy.com/submission/2761667/

    题解:

    kruskal重构树的(log^2)做法非常显然,这里就不讲了。

    这里讲讲有根树的点分治做法。

    依旧是分治,对一个分治子树,考虑所有经过分治重心的路径。

    设这个分治子树中在原树上深度最小的点为它的根(root),分治重心为(x)

    由于必须是上到下的路径,因为要经过(x),所以路径的起点一定是(root)(x)的路径上的点,而终点就是除(root)所在(x)的子树外的所有点((x)也行)。

    处理一下每个点到(x)的边权最小值,再把可以作为终点的点以这个排序,每次修改时就二分一个后缀,然后树状数组加即可。

    时间复杂度:(O(n~log^2~n))

    有根树点分治可以做更多的事情,做这道题有点杀鸡焉用牛刀。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int N = 1e5 + 5;
    
    int n, Q;
    int x, y, z, op;
    int a[N];
    
    int fi[N], to[N * 2], nt[N * 2], w[N * 2], tot;
    
    void link(int x, int y, int z) {
    	nt[++ tot] = fi[x], to[tot] = y, w[tot] = z, fi[x] = tot;
    }
    
    void Init() {
    	scanf("%d %d", &n, &Q);
    	fo(i, 1, n) scanf("%d", &a[i]);
    	fo(i, 1, n - 1) {
    		scanf("%d %d %d", &x, &y, &z);
    		link(x, y, z); link(y, x, z);
    	}
    }
    
    int dep[N];
    namespace sub1 {
    	int bz[N];
    	void dg(int x) {
    		bz[x] = 1;
    		for(int i = fi[x]; i; i = nt[i]) {
    			int y = to[i]; if(bz[y]) continue;
    			dep[y] = dep[x] + 1;
    			dg(y);
    		}
    	}
    }
    
    int siz[N], mx[N], G, bz[N];
    
    void fg(int x) {
    	bz[x] = 1;
    	siz[x] = 1; mx[x] = 0;
    	for(int i = fi[x]; i; i = nt[i]) {
    		int y = to[i]; if(bz[y]) continue;
    		fg(y);
    		siz[x] += siz[y];
    		mx[x] = max(mx[x], siz[y]);
    	}
    	mx[x] = max(mx[x], siz[0] - siz[x]);
    	if(mx[x] < mx[G]) G = x;
    	bz[x] = 0;
    }
    
    int D, FR;
    
    int mi[18][N], fr[18][N], id[18][N];
    
    int d[N], d0;
    
    int fa[N];
    
    int cd[N];
    
    void dfs(int x, int s, int la) {
    	fa[x] = la;
    	bz[x] = 1;
    	mi[D][x] = s;
    	fr[D][x] = FR;
    	d[++ d0] = x;
    	for(int i = fi[x]; i; i = nt[i]) {
    		int y = to[i]; if(bz[y]) continue;
    		dfs(y, min(s, w[i]), x);
    	}
    	bz[x] = 0;
    }
    
    int ok[18][N];
    
    int cmpd(int x, int y) {
    	return mi[D][x] < mi[D][y];
    }
    
    vector<int> e[N];
    vector<ll> f[N];
    #define pb push_back
    #define si size()
    
    int ie[18][N];
    
    int fq[N];
    
    void dg(int de, int x) {
    	fg(x);
    	cd[x] = de;
    	
    	D = de;
    	mi[D][x] = 1e9;
    	
    	d[d0 = 1] = x;
    	
    	fa[x] = 0;
    	bz[x] = 1;
    	for(int i = fi[x]; i; i = nt[i]) {
    		int y = to[i]; if(bz[y]) continue;
    		FR = y;
    		dfs(y, w[i], x);
    	}
    	
    	int rt = x;
    	fo(i, 1, d0) if(dep[d[i]] < dep[rt])
    		rt = d[i];
    	
    	fo(i, 1, d0) id[D][d[i]] = x;
    	
    	for(int p = rt; p; p = fa[p]) {
    		ok[D][p] = 1;
    	}
    	
    	for(int i = 1; i <= d0; i ++) if(d[i] != x && fr[D][d[i]] == fr[D][rt]) {
    		swap(d[i], d[d0]); d0 --; i --;
    	}
    	
    	sort(d + 1, d + d0 + 1, cmpd);
    	
    	e[x].pb(0);
    	fo(i, 1, d0) {
    		e[x].pb(d[i]);
    		ie[D][d[i]] = i;
    	}
    	f[x].resize(e[x].si);
    	 
    	bz[x] = 1;
    	for(int i = fi[x]; i; i = nt[i]) {
    		int y = to[i]; if(bz[y]) continue;
    		siz[0] = siz[y], G = 0, fg(y);
    		fq[G] = x;
    		dg(de + 1, G);
    	}
    }
    
    void build() {
    	dep[1] = 1;
    	sub1 :: dg(1);
    	
    	siz[0] = mx[0] = n;
    	
    	G = 0, fg(1), dg(0, G);
    }
    
    #define low(x) ((x) & -(x))
    void add(vector<ll> &f, int x, ll y) {
    	for(; x < f.si; x += low(x)) f[x] += y;
    }
    ll sum(vector<ll> &f, int x) {
    	ll s = 0;
    	for(; x; x -= low(x)) s += f[x];
    	return s;
    }
    
    ll qry(int x) {
    	ll ans = 0;
    	for(int p = x; p; p = fq[p]) {
    		int D = cd[p];
    		
    		if(ie[D][x]) {
    			ans += sum(f[p], ie[D][x]);
    		}
    	}
    	return ans;
    }
    
    void xiu(int x, int y, int z) {
    	for(int p = x; p; p = fq[p]) {
    		int D = cd[p];
    		if(ok[D][x] && mi[D][x] >= y) {
    			int as = -1;
    			for(int l = 1, r = e[p].si - 1; l <= r; ) {
    				int m = l + r >> 1;
    				if(mi[D][e[p][m]] >= y) {
    					as = m, r = m - 1;
    				} else l = m + 1;
    			}
    			if(as != -1) {
    				add(f[p], as, z);
    			}
    		}
    	}
    }
    
    void End() {
    	fo(ii, 1, Q) {
    		scanf("%d", &op);
    		if(op == 1) {
    			scanf("%d", &x);
    			pp("%lld
    ", qry(x) + a[x]);
    		} else {
    			scanf("%d %d %d", &z, &y, &x);
    			xiu(x, y, z);
    		}
    	}
    }
    
    int main() {
    	Init();
    	build();
    	End();
    }
    
  • 相关阅读:
    类的几个内置函数,装饰器
    面向对象,类的介绍
    模块,包,获取命令行的输入
    三元运算 ,列表推导式,迭代器,生成器
    测试运行kafka的时候缺少包的错误
    mysql5.5版本以后插入中午显示问号的解决办法
    mysql 不能插入中文和显示中文
    WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
    Hive环境的安装部署(完美安装)(集群内或集群外都适用)(含卸载自带mysql安装指定版本)
    hive的安装,一般不容易察觉的hdfs的配置问题导致hive安装的失败
  • 原文地址:https://www.cnblogs.com/coldchair/p/13423705.html
Copyright © 2011-2022 走看看