2020 ccpc长春 D. Meaningless Sequence(按位启发式合并)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020 ccpc长春 D. Meaningless Sequence(按位启发式合并)相关的知识,希望对你有一定的参考价值。
刚好在 g y m gym gym碰到就顺手写了
话说打长春的时候是被队友秒掉的emm
自己写的时候还是有点细节的…
注意虽然这是一颗有根树,但边并不是完全由父亲指向儿子的!!!
需要建双向边,我被这个卡疯了…
∑ i = 1 n ∑ j = i + 1 n [ a i ⊕ a j = a l c a i , j ] ∗ ( i ⊕ j ) \\sum\\limits_{i=1}^n\\sum\\limits_{j=i+1}^n[a_i\\oplus a_j=a_{lca_{i,j}}]*(i\\oplus j) i=1∑nj=i+1∑n[ai⊕aj=alcai,j]∗(i⊕j)
发现可以枚举每个点作为 l c a lca lca来计算贡献
那么对于 u u u子树内的点 v v v
若子树中存在另外的节点 k k k满足 a k = a u ⊕ a k a_k=a_u\\oplus a_k ak=au⊕ak就可以产生贡献
发现快速找到 a u ⊕ a k a_u \\oplus a_k au⊕ak只需要开个桶即可
v a l [ i ] [ j ] [ 0 / 1 ] val[i][j][0/1] val[i][j][0/1]表示当前子树内 a a a值为 i i i的节点中,二进制第 j j j位有多少个节点是 0 / 1 0/1 0/1
那么这个数字可以用树上启发式合并处理
然后就是枚举子树内每个点,一边计算贡献,一边把子树加入数组
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
const int N = 1e5+10;
vector<int>vec[N];
int n,a[N],dfn[N],low[N],top[N],id,siz[N],son[N];
void dfs(int u,int fa)
{
siz[u] = 1; dfn[u] = ++id; top[id] = u;
for( auto v:vec[u] )
{
if( v==fa ) continue;
dfs(v,u);
siz[u] += siz[v];
if( siz[son[u]]<siz[v] ) son[u] = v;
}
low[u] = id;
}
int SON,val[maxn][21][2];
long long ans;
//val[i][j][0/1]表示权值为i中二进制第j位为0/1的有多少个
void update(int ID,int w)
{
for(int q=0;q<=20;q++)
val[a[ID]][q][(ID>>q)&1] += w;
}
void calc(int u,int fa)
{
update( u,1 );
for( auto v:vec[u] )
{
if( v==SON || v==fa ) continue;
for(int j=dfn[v];j<=low[v];j++)
{
int ID = top[j];
for(int q=0;q<=20;q++)
if( (a[u]^a[ID])<=1e6 )
ans += 1ll*(1<<q)*val[a[u]^a[ID]][q][1^((ID>>q)&1)];
}
for(int j=dfn[v];j<=low[v];j++) update( top[j],1 );
}
}
void del(int u)
{
for(int i=dfn[u];i<=low[u];i++) update( top[i],-1 );
}
void dsu(int u,int fa,int keep)
{
for(auto v:vec[u] )
if( v!=son[u] && v!=fa ) dsu(v,u,0);
if( son[u] ) dsu( son[u],u,1 ),SON = son[u];
calc(u,fa); SON = 0;//计算以u为lca的所有答案
if( !keep ) del(u);
}
int main()
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<n;i++)
{
int l,r;scanf("%d%d",&l,&r);
vec[l].push_back( r ); vec[r].push_back( l );
}
dfs(1,1); dsu(1,1,0);
cout << ans;
}
以上是关于2020 ccpc长春 D. Meaningless Sequence(按位启发式合并)的主要内容,如果未能解决你的问题,请参考以下文章
2020CCPC 长春 L. Coordinate Paper(思维,构造)
2020第6届中国大学生程序设计竞赛CCPC长春站, 签到题3题
2020第6届中国大学生程序设计竞赛CCPC长春站, 签到题3题
2020 CCPC 长春 J. Abstract Painting(状压dp)