2020 ccpc长春 D. Meaningless Sequence(按位启发式合并)
发布日期:2021-06-30 10:33:30 浏览次数:2 分类:技术文章

本文共 1626 字,大约阅读时间需要 5 分钟。

刚好在 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=1nj=i+1n[aiaj=alcai,j](ij)

发现可以枚举每个点作为 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=auak就可以产生贡献

发现快速找到 a u ⊕ a k a_u \oplus a_k auak只需要开个桶即可

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 
using namespace std;const int maxn = 1e6+10;const int N = 1e5+10;vector
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]]
>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)&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

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/117232970 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:2020 CCPC 长春 K. Ragdoll(预处理+启发式合并)
下一篇:2019 China Collegiate Programming Contest Final (CCPC-Final 2019) L. Lottery(二进制)

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月28日 07时44分30秒