6
16
2015
0

bzoj 4134: ljw和lzr的hack比赛

我才不会说是被题目吸引进来的

然后就吓傻了,我还以为是那种朴素的森林取子问题,节点sg就是字节点抑或+1然后错的酸爽,然后赶紧问

原来并没有什么结论因为一些点已经被放了

然后就只能暴力计算sg的值,可以使用Trie树搞一搞,然后膜了一下huzecong的题解

……

//coder : davidwang
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
using namespace std;
#define LL long long
#define X first
#define Y second
inline int read()
{
	int ret=0,f=1; char ch;
	for (ch=getchar();ch<'0' || ch>'9';ch=getchar())
		if (ch=='-') f=-f;
	for (;'0'<=ch && ch<='9';ch=getchar())
		ret=ret*10+ch-'0';
	return ret*f;
}
const int N = 100010,Log=17;
struct node{
	int lch,rch,d,flag;
}s[N*Log*2];
#define l(x) s[x].lch
#define r(x) s[x].rch
int root[N],sg[N],vis[N],sum[N],up[N],fa[N],n,a[N],cnt,tot,ans[N];
vector<int>g[N];
inline int reverse(int x){
	int ret=0;
	for (int i=1;i<=Log;i++)
		if (x>>i-1&1) ret+=1<<Log-i;
	return ret;
}
inline void push_up(int x){
	s[x].flag=s[l(x)].flag && s[r(x)].flag;
}
inline void push_down(int x){
	if (s[x].d){
		if (l(x)) s[l(x)].d^=s[x].d>>1;
		if (r(x)) s[r(x)].d^=s[x].d>>1;
		if (s[x].d&1) swap(l(x),r(x));
		s[x].d=0;
	}
}
inline int getans(int x){
	int ret=0;
	for (int i=Log;x;i--){
		push_down(x);
		if (s[l(x)].flag){
			ret+=1<<i-1;
			x=r(x);
		}else x=l(x);
	}
	return ret;
}
inline void insert(int x,int num,int d){
	push_down(x);
	if (num>>d-1&1){
		if (r(x)==0) r(x)=++cnt;
		if (d!=1) insert(r(x),num,d-1);
		else s[r(x)].flag=1;
	}else{
		if (l(x)==0) l(x)=++cnt;
		if (d!=1) insert(l(x),num,d-1);
		else s[l(x)].flag=1;
	}
	push_up(x);
}
int merge(int l,int r){
	if (l==0 || s[r].flag) return r;
	if (r==0 || s[l].flag) return l;
	push_down(r); push_down(l);
	int now = ++cnt;
	l(now)=merge(l(l),l(r));
	r(now)=merge(r(l),r(r));
	push_up(now);
	return now;
}
inline void init()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read();
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=1;i<n;i++){
		int x=read(),y=read();
		g[x].push_back(y);
		g[y].push_back(x);
	}
	for (int i=1;i<=n;i++){
		root[i]=++cnt;
	}
}
inline void dfs(int x){
	for (vector<int>::iterator it=g[x].begin();it!=g[x].end();it++){
		if (*it==fa[x]) continue;
		fa[*it]=x;
		dfs(*it);
		sum[x]^=sg[*it];
	}
	for (vector<int>::iterator it=g[x].begin();it!=g[x].end();it++){
		if (*it==fa[x]) continue;
		s[root[*it]].d^=reverse(sg[*it]^sum[x]);
		root[x]=merge(root[x],root[*it]);
	}
	if (a[x]==0) insert(root[x],sum[x],Log);
	sg[x]=getans(root[x]);
}
inline void calc(int x){
	if ((up[x]^sum[x])==0 && a[x]==0) ans[++tot]=x;
	for (vector<int>::iterator it=g[x].begin();it!=g[x].end();it++){
		if (*it==fa[x]) continue;
		up[*it]=up[x]^sum[x]^sg[*it];
		calc(*it);
	}
	return;
}
inline void print()
{
	if (tot==0){ puts("-1"); return ;}
	sort(ans+1,ans+tot+1);
	for (int i=1;i<=tot;i++){
		printf("%d\n",ans[i]);
	}
}
int main()
{
	init();
	dfs(1);
//	for (int i=1;i<=n;i++) printf("%d\n",sg[i]);
	calc(1);
	print();
	return 0;
}

 

 

Category: 未分类 | Tags: bzoj sg函数 Trie树 启发式合并 | Read Count: 635

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com