zoukankan      html  css  js  c++  java
  • SPOJ COT3

    /*
    考虑直接使用暴力来算的话   SG[i]表示以i为根的子树的SG值, 然后考虑枚举删除那个子树节点, 然后求拆成的树的sg异或值, 求mex即可 复杂度三次方
    
    然后考虑尝试 整体来做 发现对于每次子树的合并, 每棵子树种的sg值相当是异或了其他的所有子树
    
    而这个东西显然是可以用 线段树合并来维护的
    
    最后找出所有sg不为0的点即可
    
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #define ll long long
    #define M 100010
    #define mmp make_pair
    using namespace std;
    int read() {
    	int nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    int cor[M], cov[M * 60], laz[M * 60], ls[M * 60], rs[M * 60], rt[M], n, sg[M], cnt, ans[M], tot;
    vector<int> to[M];
    
    void add(int &now, int v, int deep) {
    	if(deep <= -1) return;
    	if(v & (1 << deep)) swap(ls[now], rs[now]);
    	laz[now] ^= v;
    }
    
    void pushdown(int now, int deep) {
    	if(!laz[now] || !now) return;
    	add(ls[now], laz[now], deep - 1);
    	add(rs[now], laz[now], deep - 1);
    	laz[now] = 0;
    }
    
    int merge(int now, int last, int deep) {
    	if(!now || !last) return now | last;
    	if(deep == -1) {
    		cov[now] |= cov[last];
    		return now;
    	}
    	pushdown(now, deep), pushdown(last, deep);
    	ls[now] = merge(ls[now], ls[last], deep - 1);
    	rs[now] = merge(rs[now], rs[last], deep - 1);
    	cov[now] = cov[ls[now]] && cov[rs[now]];
    	return now;
    }
    
    void insert(int &now, int v, int deep) {
    	if(!now) now = ++cnt;
    	if(deep == -1) {
    		cov[now] = 1;
    		return;
    	}
    	if(v & (1 << deep)) insert(rs[now], v, deep - 1);
    	else insert(ls[now], v, deep - 1);
    }
    
    int mex(int now, int deep) {
    	if(!now || deep == -1) return 0;
    	pushdown(now, deep);
    	if(!cov[ls[now]]) return mex(ls[now], deep - 1);
    	else return (1 << deep) + mex(rs[now], deep - 1);
    }
    
    void dfs(int now, int fa) {
    	int tmp = 0;
    	for(int i = 0; i < to[now].size(); i++) {
    		int vj = to[now][i];
    		if(vj == fa) continue;
    		dfs(vj, now);
    		tmp ^= sg[vj];
    	}
    	if(!cor[now]) insert(rt[now], tmp, 17);
    	for(int i = 0; i < to[now].size(); i++) {
    		int vj = to[now][i];
    		if(vj == fa) continue;
    		add(rt[vj], tmp ^ sg[vj], 17);
    		rt[now] = merge(rt[now], rt[vj], 17);
    	}
    	sg[now] = mex(rt[now], 17);
    }
    
    void get(int now, int fa, int anss) {
    	for(int i = 0; i < to[now].size(); i++) {
    		int vj = to[now][i];
    		if(vj == fa) continue;
    		anss ^= sg[vj];
    	}
    	if(anss == 0 && !cor[now]) ans[++tot] = now;
    	for(int i = 0; i < to[now].size(); i++) {
    		int vj = to[now][i];
    		if(vj == fa) continue;
    		get(vj, now, anss ^ sg[vj]);
    	}
    }
    
    
    int main() {
    	n = read();
    	for(int i = 1; i <= n; i++) cor[i] = read();
    	for(int i = 1; i < n; i++) {
    		int vi = read(), vj = read();
    		to[vi].push_back(vj);
    		to[vj].push_back(vi);
    	}
    	dfs(1, 0);
    	get(1, 0, 0);
    	if(tot) {
    		sort(ans + 1, ans + tot + 1);
    		for(int i = 1; i <= tot; i++) cout << ans[i] << '
    ';
    	} else puts("-1");
    	return 0;
    }
    
    
    
    
    
  • 相关阅读:
    《Web 开发基础》专题系列
    《.NET 编程结构》专题汇总(C#)
    .NET Core:使用BarTender
    .NET Core:过滤器
    .NET Core:中间件
    .NET Core:Api版本控制
    .NET Core:Token认证
    .NET Core:SignalR
    .NET Core:跨域
    .NET Core:Json和XML
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10534130.html
Copyright © 2011-2022 走看看