首页 > 其他分享 >F. Strange Memory(2022 CCPC 长春)

F. Strange Memory(2022 CCPC 长春)

时间:2023-02-16 22:47:52浏览次数:47  
标签:std 遍历 int CCPC 儿子 Strange 2022 lca 节点

F. Strange Memory(2022 CCPC 长春)

tag: dsu on tree 位运算

题目链接

题意:

有一颗n个节点的树,其中1<=n<=105 ,我们需要求解式子

i = 1 n j = i + 1 n [ a i a j = a lca ( i , j ) ] ( i j ) .

即如果 a[i]^a[j] 和 i、j最近公共祖先的值相同 我们就加上 i^j

做法:

再做这题之前我并不会启发式合并,研究半天终于懂了个大概
在dsu on tree中我们将树的儿子节点们分为重儿子和轻儿子,重儿子的节点数最多且只有一个
现在我们可以将式子 a[i]^a[j] = a[lcm] 转化为 a[i]^a[lca] = a[j],
对于一个以u为根的树,节点i属于重儿子,结点j属于轻儿子,那么显然lca(i,j) = u,我们可以遍历重儿子,再遍历轻儿子,o(n2)求贡献,但这显然不够优雅
我们可以通过位运算,设置数组cnt[a[i]^a[u]][21][2],第一维表示 a[j] = a[i]^a[u],将每个j通过二进制表示来算贡献
但这样只是算了重儿子对轻儿子的贡献,我们还要算轻儿子对轻儿子的贡献,只需要每次遍历完一个轻儿子后,将轻儿子和重儿子合并即可
为什么之后要删除轻儿子呢,因为此时的重儿子只是暂时的,如果它父亲不是重儿子,重儿子和轻儿子们又会被遍历一遍

代码:

#define fst std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout << std::fixed << std::setprecision(20)
#define le "\n"
#define ll long long 
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
const int mod=998244353;
int a[N],son[N],sz[N];
vector<int> g[N];
int cnt[(1<<20)+7][21][2]; //为了统计和方便计算 a[j] = a[i]^a[lca] 的j,将每个j进行二进制表示来算贡献
ll ans;

void predfs(int u,int fa){
    sz[u] = 1;
    for(auto i: g[u]){
        if(i==fa) continue;
        predfs(i,u);
        sz[u] += sz[i];
        if(sz[i]>sz[son[u]]) son[u] = i;//计入重儿子
    }
}

void cal(int x,int y){
    for(int i=0;i<20;i++){
        if(y&(1<<i)) ans += (1ll<<i)*cnt[x][i][0];
        else ans += (1ll<<i)*cnt[x][i][1];
    }
}

void update(int u,int fa,int tf,int val){
    for(int i=0;i<20;i++){
        if(u&(1ll<<i)) cnt[a[u]][i][1] += val;
        else cnt[a[u]][i][0] += val;
    }
    for(auto v: g[u]){
        if(v==fa||v==son[tf]) continue;//注意这里是tf的重儿子而不是fa的重儿子
        update(v,u,tf,val);
    }
}

void count(int u,int fa,int tf){//tf标记待统计子树的根
    cal(a[u]^a[tf],u);
    for(auto v: g[u]){
        if(v==fa||v==son[tf]) continue;
        count(v,u,tf);//暴力遍历所有轻儿子的节点 
        if(u==tf) update(v,u,tf,1);//加上轻儿子,我们不仅要算轻儿子对重儿子的贡献,还要算轻儿子对重儿子的贡献
    }
    if(u==tf){
        for(auto v: g[u]){
            if(v==fa||v==son[tf]) continue;
            update(v,u,tf,-1);//删去轻儿子
        }
    }
}

void dfs(int u,int fa,int op){
    for(auto v: g[u]){
        if(v==son[u]||v==fa) continue;
        dfs(v,u,0);//首先遍历u的轻儿子算贡献
    }
    if(son[u]) dfs(son[u],u,1); //遍历u的重儿子算贡献
    count(u,fa,u);
    update(u,fa,u,1);//把u的二进制上传,此刻只保留了u和重儿子的二进制情况
    if(!op) update(u,fa,0,-1);//当前为u为fa的轻儿子,则删除贡献
}


int main() {
    fst;
    int n; cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<n;i++){
        int u,v; cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    predfs(1,0);
    dfs(1,0,1);
    cout<<ans<<le;
    return 0;
}   

标签:std,遍历,int,CCPC,儿子,Strange,2022,lca,节点
From: https://www.cnblogs.com/touchfishman/p/17128558.html

相关文章

  • 连续两年榜上有名!TDengine 荣获墨天轮“2022 年度时序数据库”奖项
    随着一系列利好政策的发布,国产数据库行业正在发生翻天覆地的变化,投融资此起彼伏,国产化替代进程加速,国产数据库行业发展如火如荼。在此背景下,墨天轮颁布了《2022年度数据......
  • J. Abstract Painting (2020 CCPC 长春)
    J.AbstractPaintingtag:dp题目链接题意:有个很抽象的人要画一幅抽象画,这个抽象画只需要画圆圈就完事了(我上我也行)需要满足以下条件圆心都必须在x轴上的[1,n]上,且必......
  • 2022.2.1最新版本的IDEA
       一、下载破解工具、激活码激活工具下载链接:https://note.youdao.com/s/1ANz2F3o 6G5NXCPJZB-eyJsaWNlbnNlSWQiOiI2RzVOWENQSlpCIiwibGljZW5zZWVOYW1lIjoic2l......
  • 「解题报告」[NOI2022] 冒泡排序
    前排膜拜happyguy感觉这种特殊性质给的很多的题就应该把特殊性质挨个进行分析。特殊性质A首先容易发现:\(V_i\in[0,1]\),那么\(a_i\in[0,1]\)。显然这样不劣。......
  • 2022年最新数据库调查报告:超八成DBA月薪过万,你拖后腿了吗?
    数据库管理员属于IT行业高薪职业的一种,近几年关于数据库管理员的薪资统计文章也层出不穷,那么当前,DBA们的薪资究竟到达了怎样的水平呢?墨天轮数据社区发布最新《2022年墨天......
  • [省选联考 2022] 填树 题解
    神奇dp。发现我看到dp大多数时候只会暴力。那我约等于退役了啊。题意:自己看。首先有一个显然的暴力。枚举一个最小值\(L\),然后区间就限定在了\([L,L+K]\)。那么普及......
  • IDEA 2022.02新建web工程
    1、创建项目 2、新建代码目录创建后的目录如下:3、添加web配置此时代码目录中会多出如下目录 4、配置tomcat点击运行配置,新增tomcatserver并配置tomcat地址......
  • 基于Moduli N = (p^r)*q的RSA新攻击方法(结合[强网杯2022]factor进行讲解)
      此篇文章的灵感来源于[强网杯2022]factor,其中就用到了3种基于ModuliN=(p^r)*q的RSA新攻击方法,有兴趣可以看看原paper399.pdf(iacr.org)       定......
  • CSP2022 假期计划 题解
    给你一张\(n\)个点,\(m\)条边的无向图,每个点有点权,要求你在图中选出\(A\),\(B\),\(C\),\(D\)四个点,使得\(1\rightarrowA\rightarrowB\rightarrowC\righ......
  • 2022强网拟态 WHOYOUARE
    2022强网拟态WHOYOUARE先说一下这个思路由于禁用了__proto__所以我们可以通过constructor.prototype来绕过之前一直不明白为什么是这样绕过的后来仔细研究了一下本人......