Codeforces Round #430 (Div. 2)C. Ilya And The Tree dfs D - Vitya and Strange Lesson

http://codeforces.com/contest/842/problem/C

树上每个点都有一个权值,求每一个点到根节点路径上所有节点的最大公因子,可以删掉任意一个点,也可以不删

删掉一个点影响的只是这个点的所有孩子节点,所有枚举每个点被删掉的情况,这样复杂度是n^2,加一些剪枝,

1.当到根节点的路径上的最大公因子已经是1,则没必要继续向下搜索了

2.当删掉这个点后得到的gcd等于不删这个节点的gcd,则没必要枚举删掉这个点的情况

#include<bits/stdc++.h>
#define eps 1e-9
#define PI 3.141592653589793
#define bs 1000000007
#define bsize 256
#define MEM(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std;
int n;
int a[200005];
vector<int>w[200005];
int t[200005],ans[200005];
void dfs1(int x,int fa)
{	
	if(t[x]>ans[x])
	ans[x]=t[x];
	for(int i=0;i<w[x].size();i++)
	{
		if(w[x][i]==fa)
		continue;
		int temp=__gcd(a[w[x][i]],t[x]);
		if(temp==1)
		continue;
		t[w[x][i]]=temp;
		dfs1(w[x][i],x);
	}
}
void dfs(int x,int fa)
{
	if(t[x]>ans[x])
	ans[x]=t[x];
	if(t[x]==1)
	return ;
	
	for(int i=0;i<w[x].size();i++)
	{
		if(w[x][i]==fa)
		continue;
		int temp=__gcd(t[x],a[w[x][i]]);
		
		if(temp!=t[x])
		{
			t[w[x][i]]=t[x];
			dfs1(w[x][i],x);
		}
		t[w[x][i]]=temp;	
		dfs(w[x][i],x);
	}
}

int main()
{
	int i,x,y;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		ans[i]=1;
	}
	for(i=1;i<n;i++)
	{
		scanf("%d %d",&x,&y);
		w[x].push_back(y);
		w[y].push_back(x);
	}
	w[0].push_back(1);
	dfs(0,0);
	for(i=1;i<=n;i++)
	printf("%d ",ans[i]);
	cout<<endl;
	return 0;
 }

http://codeforces.com/contest/842/problem/D

数列里有n个数,m次操作,每次给x,让n个数都异或上x。并输出数列的mex值

01trie,相当于按位记录,顶点是最高位,要找异或最大,则向此位数值相反的结点走,要求异或最小,则向此位数值相同的结点走


#include<bits/stdc++.h>
using namespace std;
const int maxn=500005;
int s[30];
struct node
{
	int l,r,x;
}seg[maxn*4];
void build(int l,int r,int node)
{
	seg[node].l=l;
	seg[node].r=r;
	if(l==r)
	{
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,node<<1);
	build(mid+1,r,node<<1|1);
	return ;
}
void update(int node,int k)
{
	if(seg[node].l==seg[node].r)
	{
		seg[node].x=1;
		return ;
	}
	int mid=(seg[node].l+seg[node].r)>>1;
	if(mid>=k)
	update(node<<1,k);
	else
	update(node<<1|1,k);
	seg[node].x=seg[node<<1].x+seg[node<<1|1].x;
	return ;
}
int query(int node,int k)
{
	if(seg[node].l==seg[node].r)
	{
		return 0;
	}
	int temp=node<<1|s[k];
	if(seg[temp].x==seg[temp].r-seg[temp].l+1)
	{
		return query(temp^1,k-1)+(1<<k);
	}
	else
	{
		return query(temp,k-1);
	}
}
int main()
{
	int n,m,i,j,a;
	cin>>n>>m;
	build(0,524287,1);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&a);
		update(1,a);
	}
	int now=0;
	while(m--)
	{
		scanf("%d",&a);
		now^=a;
		for(i=0;i<19;i++)
		{
			s[i]=(now&(1<<i))==(1<<i);
		}
		printf("%d\n",query(1,18));
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值