考虑哪些点对无论颜色怎么变都是没有用的(不可能成为答案)。
先把 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;
}
标签:ch,lc,XSY4184,01Trie,int,who,rc,lca,标记
From: https://www.cnblogs.com/ez-lcw/p/16842977.html