zoukankan      html  css  js  c++  java
  • Gym102832F.Strange Memory(树上启发式合并+STL)

    给出一棵树。

    当两个点的点权异或和等于它们LCA的点权的时候,它们的下标异或和会被统计到答案里。

    询问答案。

    对同一个点,它不同子树内的点点权异或和等于这个点的点权的时候,可以作为答案。

    那么就先对最大的那颗子树维护一个map,剩下的点往最大的这颗子树上合并

    这个点的map可以继续往上合并

    map<int,vector > mp;表示值为x的下标

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    vector<int> g[maxn];
    int a[maxn],n,size[maxn];
    int son[maxn];
    long long ans=0;
    void dfs1 (int x,int pre) {
    	size[x]=1;
    	for (int y:g[x]) {
    		if (y==pre) continue;
    		dfs1(y,x);
    		size[x]+=size[y];
    		if (size[y]>size[son[x]]) {
    			son[x]=y;
    		}
    	}
    } 
    map<int,vector<int> > dfs2 (int x,int pre) {
    	if (!son[x]) {
    		map<int,vector<int> > mp;
    		mp[a[x]].push_back(x);
    		return mp;
    	}
    	map<int,vector<int> > mp=dfs2(son[x],x);
    	for (int y:g[x]) {
    		if (y==pre||y==son[x]) continue;
    		map<int,vector<int> > mp1=dfs2(y,x);
    		for (auto it=mp1.begin();it!=mp1.end();it++) {
    			for (int j:it->second)
    				for (int k:mp[a[x]^it->first]) {
    					ans+=j^k;
    				}
    		} 
    		for (auto it=mp1.begin();it!=mp1.end();it++) {
    			for (int j:it->second) mp[it->first].push_back(j);
    		}
    	}
    	mp[a[x]].push_back(x);
    	return mp;
    }
    int main () {
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++) scanf("%d",a+i);
    	for (int i=1;i<n;i++) {
    		int x,y;
    		scanf("%d%d",&x,&y);
    		g[x].push_back(y);
    		g[y].push_back(x);
    	}
    	dfs1(1,0);
    	//for (int i=1;i<=n;i++) printf("%d ",son[i]);
    	//printf("
    ");
    	map<int,vector<int> > mp=dfs2(1,0);
    	printf("%lld
    ",ans);
    }
  • 相关阅读:
    战旗游戏系统分析
    战棋游戏的战术性
    利用JSFL制作swf素材包
    深刻理解Java编程的7个例子
    ORACLE SQL:经典查询练手第二篇
    删除U盘时提示无法停止“通用卷”设备
    ORACLE SQL:经典查询练手第四篇
    IE8中打不开oracle EBS画面 FRM92050
    ORACLE SQL:经典查询练手第三篇
    ORACLE SQL:经典查询练手第一篇
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14594029.html
Copyright © 2011-2022 走看看