zoukankan      html  css  js  c++  java
  • [动态树分治]

    最近学习了一下动态树分治。刷了一些比较基础的题目

    一般都是存一下到这个重心的信息,然后再存这棵子树到上一层重心的信息,搞一搞就可以了

    [COGS 2278]树黑白

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define maxn 200010
    using namespace std;
    typedef long long ll;
    int n, m;
    //-------------------------------------------------//
    struct Edge{int to, nxt, dis;}edge[maxn << 1];
    int h[maxn], cnt;
    void add(int u, int v, int d){
    	cnt ++;
    	edge[cnt].to = v;
    	edge[cnt].nxt = h[u];
    	edge[cnt].dis = d;
    	h[u] = cnt;
    }
    //-------------------------------------------------//
    ll dis[maxn];
    int dep[maxn], fa[maxn], anc[maxn][20];
    void dfs(int u){
    	dep[u] = dep[fa[u]] + 1;
    	for(int i = h[u]; i; i = edge[i].nxt){
    		int v = edge[i].to;
    		if(v == fa[u])continue;
    		dis[v] = dis[u] + edge[i].dis;
    		fa[v] = u;
    		dfs(v);
    	}
    }
    
    int ask_LCA(int p, int q){
    	if(dep[p] < dep[q])swap(p, q);
    	int log = 1;
    	for(; 1 << log <= dep[p]; log ++); log --;
    	for(int i = log; i >= 0; i --)
    	    if(anc[p][i] && dep[anc[p][i]] >= dep[q])
    	        p = anc[p][i];
    	if(p == q)return p;
    	for(int i = log; i >= 0; i --)
    	    if(anc[p][i] && anc[p][i] != anc[q][i])
    	        p = anc[p][i], q = anc[q][i];
    	return fa[p];
    }
    
    ll dist(int p, int q){return dis[p] + dis[q] - 2 * dis[ask_LCA(p, q)];}
    //-------------------------------------------------//
    int g[maxn], size[maxn], G, Sum;
    bool vis[maxn], check[maxn];
    void Get_G(int u, int fa){
    	size[u] = 1;
    	int f = 0;
    	for(int i = h[u]; i; i = edge[i].nxt){
    		int v = edge[i].to;
    		if(v == fa || vis[v])continue;
    		Get_G(v, u);
    		size[u] += size[v];
    		f = max(f, size[v]);
    	}
    	f = max(f, Sum - size[u]);
    	if((f << 1) <= Sum)G = u;
    }
    
    void Divide(int u, int f){
    	g[u] = f;
    	vis[u] = true;
    	for(int i = h[u]; i; i = edge[i].nxt){
    		int v = edge[i].to;
    		if(vis[v])continue;
    		Sum = size[v], G = v;
    		Get_G(v, u);
    		Divide(G, u);
    	}
    }
    //-------------------------------------------------//
    
    ll Node[maxn], Dis[maxn], Disf[maxn], ans;
    int Standard;
    
    void White(int u){
    	Node[u] --;
    	Dis[u] -= dist(u, Standard);
    	if(g[u] == -1)return;
    	Disf[u] -= dist(g[u], Standard);
    	White(g[u]);
    }
    
    void Black(int u){
    	Node[u] ++;
    	Dis[u] += dist(u, Standard);
    	if(g[u] == -1)return;
    	Disf[u] += dist(g[u], Standard);
    	Black(g[u]);
    }
    
    void ask(int u){
    	ans += (Node[u] * dist(u, Standard) + Dis[u]);
    	if(g[u] == -1)return;
    	ans -= (Node[u] * dist(g[u], Standard) + Disf[u]);
    	ask(g[u]);
    }
    
    int main(){
        freopen("A_Tree.in", "r", stdin);
    	freopen("A_Tree.out", "w", stdout);
    	scanf("%d%d", &n, &m);
    	int u, v, d;
    	for(int i = 1; i < n; i ++){
    		scanf("%d%d%d", &u, &v, &d);
    		add(u, v, d), add(v, u, d);
    	}
    
    	dfs(1); Sum = n;
    	Get_G(1, -1), Divide(G, -1);
    	for(int i = 1; i <= n; i ++)
    	    anc[i][0] = fa[i];
    	for(int j = 1; 1 << j <= n; j ++)
    	    for(int i = 1; i <= n; i ++)
    	        anc[i][j] = anc[anc[i][j-1]][j-1];
    	char cmd[2];
    	while(m --){
    		scanf("%s%d", cmd, &u);
    		Standard = u;
    		if(cmd[0] == 'Q'){
    			ans = 0;
    			ask(u);
    			printf("%lld
    ", ans);
    		}
    		else{
    			if(check[u])White(u);
    			else Black(u);
    			check[u] ^= 1;
    		}
    	}
    	return 0;
    }
    

    [COGS 2258]复仇的序幕曲

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #define maxn 100010
    using namespace std;
    
    struct Edge{int to, nxt, dis;}edge[maxn << 1];
    int h[maxn], cnt;
    void add(int u, int v, int d){
    	cnt ++;
    	edge[cnt].to = v;
    	edge[cnt].nxt = h[u];
    	edge[cnt].dis = d;
    	h[u] = cnt;
    }
    
    int n, m, a[maxn];
    
    int dis[maxn], fa[maxn], anc[maxn][20], dep[maxn];
    void dfs(int u){
    	dep[u] = dep[fa[u]] + 1;
    	for(int i = h[u]; i; i = edge[i].nxt){
    		int v = edge[i].to;
    		if(v == fa[u])continue;
    		fa[v] = u;
    		dis[v] = dis[u] + edge[i].dis;
    		dfs(v);
    	}
    }
    
    int ask_LCA(int p, int q){
    	if(dep[p] < dep[q])swap(p, q);
    	int log = 1;
    	for(; 1 << log <= dep[p]; log ++); log --;
    	for(int i = log; i >= 0; i --)
    		if(anc[p][i] && dep[anc[p][i]] >= dep[q])
    		    p = anc[p][i];
    	if(p == q)return p;
    	for(int i = log; i >= 0; i --)
    	    if(anc[p][i] && anc[p][i] != anc[q][i])
    	        p = anc[p][i], q = anc[q][i];
    	return fa[p];
    }
    
    int dist(int p, int q){
    	return dis[p] + dis[q] - 2 * dis[ask_LCA(p, q)];
    }
    
    //-----------------------------------------------//
    bool vis[maxn];
    int g[maxn], size[maxn], G, Sum;
    vector<pair<int, int> > V[maxn], F[maxn];
    
    void Get_G(int u, int fa){
    	int f = 0; size[u] = 1;
    	for(int i = h[u]; i; i = edge[i].nxt){
    		int v = edge[i].to;
    		if(vis[v] || v == fa)continue;
    		Get_G(v, u);
    		size[u] += size[v];
    		f = max(f, size[v]);
    	}
    	f = max(f, Sum - size[u]);
    	if((f << 1) <= Sum) G = u;
    }
    
    void Divide(int u, int f){
    	g[u] = f, vis[u] = true;
    	for(int i = h[u]; i; i = edge[i].nxt){
    		int v = edge[i].to;
    		if(vis[v])continue;
    		Sum = size[v], G = v;
    		Get_G(v, u), Divide(G, u);
    	}
    }
    
    int st, T, ans;
    
    void update(int u){
    	V[u].push_back(make_pair(dist(st, u), a[st]));
    	F[u].push_back(make_pair(dist(st, g[u]), a[st]));
    	if(g[u] > 0)update(g[u]);
    }
    
    int Binarysearch(vector<pair<int, int> > &V, int nw){
    	if(V[0].first > nw)return 0;
    	int l = 0, r = V.size() - 1;
    	while(l < r){
    		int m = l + (r - l + 1) / 2;
    		if(V[m].first > nw)
    			r = m - 1;
    		else l = m;
    	}
    	return V[l].second;
    }
    
    void ask(int u){
    	ans += Binarysearch(V[u], T - dist(u, st));
    	if(g[u] == -1)return;
    	int d = dist(g[u], st);
    	ans -= Binarysearch(F[u], T - d);
    	ask(g[u]);
    }
    //-----------------------------------------------//
    int main(){
    	freopen("SS.in", "r", stdin);
    	freopen("SS.out", "w", stdout);
    	scanf("%d%d", &n, &m);
    	for(int i = 1; i <= n; i ++)
    	    scanf("%d", &a[i]);
    	int u, v, d;
    	for(int i = 1; i < n; i ++){
    		scanf("%d%d%d", &u, &v, &d);
    		add(u, v, d), add(v, u, d);
    	}
    	
    	dfs(1);
    	for(int i = 1; i <= n; i ++)
    	    anc[i][0] = fa[i];
    	for(int j = 1; 1 << j <= n; j ++)
    	    for(int i = 1; i <= n; i ++)
    	        anc[i][j] = anc[anc[i][j-1]][j-1];
    	Sum = n;
    	Get_G(1, -1), Divide(G, -1);
    	
    	for(int i = 1; i <= n; i ++)
    	    st = i, update(i);
    	int sum = 0;
        for(int i = 1; i <= n; i ++){
    		sort(V[i].begin(), V[i].end());
    		sort(F[i].begin(), F[i].end());
    		sum = 0;
    		for(int j = 0; j < V[i].size(); j ++){
    			sum += V[i][j].second;
    			V[i][j].second = sum;
    		}
    		
    		sum = 0;
    		for(int j = 0; j < F[i].size(); j ++){
    			sum += F[i][j].second;
    			F[i][j].second = sum;
    		}
        }
        
    	while(m --){
    		scanf("%d%d", &st, &T);
    		ans = 0, ask(st);
    		printf("%d
    ", ans);
    	}
    	
    	return 0;
    }
    

    [HNOI 2015]开店

    并不清楚为什么要写G=v;这句话,难道找不到么。。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #define maxn 150010
    using namespace std;
    typedef long long ll;
    typedef vector<pair<int, ll> > vp;
    int n, Q, A;
    
    struct Edge{int to, nxt, dis;}edge[maxn << 1];
    int h[maxn], cnt;
    void add(int u, int v, int w){
    	cnt ++;
    	edge[cnt].to = v;
    	edge[cnt].nxt = h[u];
    	edge[cnt].dis = w;
    	h[u] = cnt;
    }
    
    
    int a[maxn];
    
    //-----------------------------------------------------//
    int dep[maxn], fa[maxn], anc[maxn][20];
    ll dis[maxn];
    void dfs(int u){
    	dep[u] = dep[fa[u]] + 1;
    	for(int i = h[u]; i; i = edge[i].nxt){
    		int v = edge[i].to;
    		if(v == fa[u])continue;
    		fa[v] = u;
    		dis[v] = dis[u] + edge[i].dis;
    		dfs(v);
    	}
    }
    
    void pre_LCA(){
    	for(int i = 1; i <= n; i ++)
    	    anc[i][0] = fa[i];
    	for(int j = 1; 1 << j <= n; j ++)
    		for(int i = 1; i <= n; i ++)
    		    anc[i][j] = anc[anc[i][j-1]][j-1];
    }
    
    int ask_LCA(int p, int q){
    	if(dep[p] < dep[q])swap(p, q);
    	int log = 1;
    	for(; 1 << log <= dep[p]; log ++); log --;
    	for(int i = log; i >= 0; i --)
    	    if(anc[p][i] && dep[anc[p][i]] >= dep[q])
    	        p = anc[p][i];
    	if(p == q)return p;
    	for(int i = log; i >= 0; i --)
    	    if(anc[p][i] && anc[p][i] != anc[q][i])
    			p = anc[p][i], q = anc[q][i];
    	return fa[p];
    }
    
    ll dist(int u, int v){
    	return dis[u] + dis[v] - 2 * dis[ask_LCA(u, v)];
    }
    
    //-----------------------------------------------------//
    
    int g[maxn], size[maxn], G, Sum;
    vp V[maxn], F[maxn];
    bool vis[maxn];
    
    void Get_G(int u, int fa){
    	size[u] = 1; int f = 0;
    	for(int i = h[u]; i; i = edge[i].nxt){
    		int v = edge[i].to;
    		if(v == fa || vis[v])continue;
    		Get_G(v, u);
    		size[u] += size[v];
    		f = max(f, size[v]);
    	}
    	f = max(f, Sum - size[u]);
    	if((f << 1) <= Sum)G = u;
    }
    
    void Divide(int u, int f){
    	g[u] = f, vis[u] = true;
    	for(int i = h[u]; i; i = edge[i].nxt){
    		int v = edge[i].to;
    		if(vis[v])continue;
    		Sum = size[v], G = v;
    		Get_G(v, u), Divide(G, u);
    	}
    }
    
    int St;
    
    void update(int u){
    	V[u].push_back(make_pair(a[St], dist(St, u)));
    	if(g[u] < 0) return;
    	F[u].push_back(make_pair(a[St], dist(St, g[u])));
    	update(g[u]);
    }
    
    ll ans = 0;
    int L, R;
    
    int Bs(vp& V, ll nw){
    	int l = 0, r = V.size() - 1;
    	while(l < r){
    		int m = l + (r - l + 1) / 2;
    		if(V[m].first <= nw)l = m;
    		else r = m - 1;
    	}
    	return l;
    }
    
    ll Binarysearch(vp &V, ll dis){
    	if(V[0].first > R)return 0;
    	if(V[V.size()-1].first < L)return 0;
    	int ret1 = Bs(V, L-1), ret2 = Bs(V, R);
    	return dis * (ret2 - ret1) + V[ret2].second - V[ret1].second;
    }
    
    void ask(int u){
    	ans += Binarysearch(V[u], dist(St, u));
    	if(g[u] < 0)return;
    	ans -= Binarysearch(F[u], dist(St, g[u]));
    	ask(g[u]);
    }
    
    int main(){
    	freopen("shop_hnoi2015.in", "r", stdin);
    	freopen("shop_hnoi2015.out", "w", stdout);
    	scanf("%d%d%d", &n, &Q, &A);
    	for(int i = 1; i <= n; i ++)
    	    scanf("%d", &a[i]);
    	int u, v, d; 
    	for(int i = 1; i < n; i ++){
    		scanf("%d%d%d", &u, &v, &d);
    		add(u, v, d), add(v, u, d);
    	}
    	dfs(1), pre_LCA(), Sum = n;
    	Get_G(1, -1), Divide(G, -1);
    	for(int i = 1; i <= n; i ++)
    	    update(St = i);
    	for(int i = 1; i <= n; i ++){
    		V[i].push_back(make_pair(-1, 0));
    		F[i].push_back(make_pair(-1, 0));
    		sort(V[i].begin(), V[i].end());
    		sort(F[i].begin(), F[i].end());
    		for(int j = 1; j < V[i].size(); j ++)
    			V[i][j].second += V[i][j-1].second;
    		for(int j = 1; j < F[i].size(); j ++)
    		    F[i][j].second += F[i][j-1].second;
    	}
    	
    	
    	while(Q --){
    		scanf("%d%d%d", &u, &L, &R);
    		L = (L + ans) % A, R = (R + ans) % A;
    		if(L > R)swap(L, R);
    		St = u, ans = 0, ask(u);
    		printf("%lld
    ", ans);
    	}
    
        return 0;
    }
    

      

    给时光以生命,而不是给生命以时光。
  • 相关阅读:
    取得GridPanel选定行所有字段值
    从少林寺的核心竞争力看软件作坊和正规军的差异
    估算软件项目成本
    Delphi FastReport报表常用方法
    少林寺的组织结构分析
    embed标签使用
    C# 多种方式播放Wav声音
    js 关闭浏览器
    ExtJS GridPanel根据条件改变字体颜色
    [Jsp] 如何在JSP页面快速输出从Servlet接收的数据_看JSTL常用C标签的威力
  • 原文地址:https://www.cnblogs.com/Candyouth/p/5432441.html
Copyright © 2011-2022 走看看