【XSY4184】谁(who)(01Trie,结论)

考虑哪些点对无论颜色怎么变都是没有用的(不可能成为答案)。

先把 01Trie 建出来,对于每一个点 \(lca\),找到异或值最小的两个点 \(u,v\),使得 \(u\)\(lca\) 左子树内,\(v\)\(lca\) 右子树内,然后标记点对 \((u,v)\)。(注意这里不考虑颜色)

找到所有标记的点对可以 \(O(n\log^2 a_i)\) 实现,显然标记的点对只有 \(O(n\log a_i)\) 个,直接给出结论:除了这 \(O(n\log a_i)\) 个标记点对以外的其他点对都是没用的。

证明:对于某个点 \(lca\) 得到的标记点对 \((u,v)\),现在考虑在任意一种颜色情况下,是否存在除了 \((u,v)\) 之外的某个点对 \((u',v')\),使得 \(u\)\(lca\) 左子树内,\(v\)\(lca\) 右子树内,且点对 \((u',v')\) 不是没有用的(即 \((u',v')\) 有可能成为答案)。注意到 \((u,v')\) 可能成为答案的必要条件是此时 \(u,v'\) 异色,所以下面默认 \(u,v'\) 异色:

  • \(u,v\) 异色,则点对 \((u,v)\) 可以选,由标记点对的定义可知选 \((u,v)\) 肯定更优;
  • \(u,v\) 同色,则点对 \((u,v)\) 不能选。但由于 \(u',v'\) 异色,所以 \(u,u'\)\(v,v'\) 两者中肯定有至少一者是异色的,而点对 \((u,u')\)\((v,v')\) 显然都比点对 \((u',v')\) 更优,所以点对 \((u',v')\) 也不可能成为答案。

注意到包含某个点的标记点对至多只有 \(\log a_i\) 个,所以我们可以用 multiset 维护所有标记点对的答案,每次修改 \(u\) 的时候暴力枚举包含 \(u\) 的标记点对并修改即可。

#include<bits/stdc++.h>

#define LG 35
#define N 200010
#define lc(u) ch[u][0]
#define rc(u) ch[u][1]
#define INF 0x7fffffff

using namespace std;

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

int n,m,a[N],c[N];
int node=1,ch[N*LG][2];
int L[N*LG],R[N*LG];

vector<int>e[N];
multiset<int>s;

void adde(int u,int v)
{
	e[u].push_back(v);
	e[v].push_back(u);
}

void insert(int x,int id)
{
	int u=1;
	for(int i=29;i>=0;i--)
	{
		bool v=((x>>i)&1);
		if(!ch[u][v]) ch[u][v]=++node;
		u=ch[u][v];
	}
	if(L[u]==L[0]) L[u]=id;
	else adde(R[u],id);
	R[u]=id;
}

int query(int u,int x,int dep)
{
	for(int i=dep;i>=0;i--)
	{
		bool v=((x>>i)&1);
		if(ch[u][v]) u=ch[u][v];
		else u=ch[u][v^1];
	}
	return L[u];
}

void dfs(int u,int dep)
{
	if(lc(u))
	{
		dfs(lc(u),dep-1);
		L[u]=min(L[u],L[lc(u)]);
		R[u]=max(R[u],R[lc(u)]);
	}
	if(rc(u))
	{
		dfs(rc(u),dep-1);
		L[u]=min(L[u],L[rc(u)]);
		R[u]=max(R[u],R[rc(u)]);
	}
	if(lc(u)&&rc(u))
	{
		int aa,bb,val=INF;
		for(int i=L[lc(u)];i<=R[lc(u)];i++)
		{
			int vv=query(rc(u),a[i],dep-1);
			if((a[i]^a[vv])<val) aa=i,bb=vv,val=a[i]^a[vv];
		}
		adde(aa,bb);
	}
}

int main()
{
	freopen("who3.in","r",stdin);
	freopen("who3.out","w",stdout);
	memset(L,127,sizeof(L));
	memset(R,128,sizeof(R));
	n=read(),m=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		insert(a[i],i);
	}
	dfs(1,29);
	for(int i=1;i<=n;i++) c[i]=read();
	for(int u=1;u<=n;u++)
		for(int v:e[u])
			if(u<v&&c[u]!=c[v])
				s.insert(a[u]^a[v]);
	while(m--)
	{
		int u=read(),y=read();
		for(int v:e[u])
			if(c[u]!=c[v])
				s.erase(a[u]^a[v]);
		c[u]=y;
		for(int v:e[u])
			if(c[u]!=c[v])
				s.insert(a[u]^a[v]);
		printf("%d\n",(*s.begin()));
	}
	return 0;
}
posted @ 2022-10-31 07:47  ez_lcw  阅读(13)  评论(0编辑  收藏  举报