zoukankan      html  css  js  c++  java
  • codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(启发式合并)

    codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    题意

    给出一棵树,每条边上有一个字符,字符集大小只有22。
    对于每一个子树,询问其中最长的,满足:路径上的字符集可以重组成字符串的路径的长度。

    题解

    明显是用mask维护信息,然后启发式合并一下。
    一般启发式合并需要用map维护信息,这样的复杂度是log^2的。如果保留每个点重儿子的信息,就可以用全局变量维护,全局变量的大小就可以开很大,可以做到log。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define rep(i, a, b) for(int i=(a); i<(b); i++)
    #define sz(a) (int)a.size()
    #define de(a) cout << #a << " = " << a << endl
    #define dd(a) cout << #a << " = " << a << " "
    #define all(a) a.begin(), a.end()
    #define endl "
    "
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef vector<int> vi;
    //---
    
    const int N = 505050;
    
    int n;
    int ans[N], s[N], par[N], dep[N], wson[N], sz[N], mask[22], len[1<<22];
    vi g[N];
    vector<pii> info[N];
    
    inline void join(vector<pii> &a, vector<pii> &b, const int &t, const int &c, int &ans) {
    	if(t) swap(a, b);
    	for(auto u : b) {
    		if(~len[u.fi]) ans = max(ans, len[u.fi] + u.se - c);
    		rep(i, 0, 22) if(~len[u.fi ^ mask[i]]) {
    			ans = max(ans, len[u.fi ^ mask[i]] + u.se - c);
    		}
    	}
    	for(auto u : b) {
    		len[u.fi] = max(len[u.fi], u.se);
    	}
    	a.insert(a.end(), all(b));
    }
    
    void dfs(int u, bool isw) {
    	info[u].pb(mp(s[u], dep[u]));
    	if(sz(g[u])) {
    		for(auto v : g[u]) if(v != wson[u]) {
    			dfs(v, 0);
    			ans[u] = max(ans[u], ans[v]);
    		}
    		dfs(wson[u], 1);
    		ans[u] = max(ans[u], ans[wson[u]]);
    		join(info[u], info[wson[u]], 1, dep[u] * 2, ans[u]);
    		for(auto v : g[u]) if(v != wson[u]) {
    			join(info[u], info[v], 0, dep[u] * 2, ans[u]);
    		}
    		if(!isw) for(auto t : info[u]) len[t.fi] = -1;
    	} else {
    		if(isw) len[s[u]] = max(len[s[u]], dep[u]);
    	}
    }
    
    int main() {
    	std::ios::sync_with_stdio(false);
    	std::cin.tie(0);
    	rep(i, 0, 22) mask[i] = (1 << i);
    	cin >> n;
    	rep(i, 2, n+1) {
    		string t;
    		cin >> par[i] >> t;
    		int c = t[0] - 'a';
    		g[par[i]].pb(i);
    		s[i] = s[par[i]] ^ mask[c];
    		dep[i] = dep[par[i]] + 1;
    	}
    	for(int i = n; i; --i) {
    		sz[par[i]] += ++sz[i];
    		if(sz[wson[par[i]]] < sz[i]) wson[par[i]] = i;
    	}
    	memset(len, -1, sizeof(len));
    	dfs(1, 1);
    	rep(i, 1, n+1) cout << ans[i] << " ";
    	cout << endl;
    	return 0;
    }
    
  • 相关阅读:
    spring mvc自定义配置 mvc:annotationdriven 东师理想
    spring配置xmemcached及使用 东师理想
    fastjson的简单序列化使用(转) 东师理想
    配置springmvc + simplespringmemcached 东师理想
    利用Spring AOP 更新memcached 缓存策略的实现(二) 东师理想
    springmvc 退出清除session,返回首页,获取当前项目路径,返回前台ajax输出 东师理想
    利用Spring AOP 更新memcached 缓存策略的实现(一) 东师理想
    tomcat7 配置 jstl 东师理想
    Linear Sieve Method for Prime Numbers
    List All Of The Subsets
  • 原文地址:https://www.cnblogs.com/wuyuanyuan/p/9265181.html
Copyright © 2011-2022 走看看