NOIP2023模拟9联测30-金牌

news/2024/7/3 4:04:22

Ayano \text{Ayano} Ayano 有一棵 n n n 个顶点的树(编号从 1 1 1 n n n )。 这棵树有 n − 1 n−1 n1 条边,第 i i i 条边连接顶点 u i u_i ui 和顶点 v i v_i vi。 由于 Ayano \text{Ayano} Ayano 非常喜欢这棵树,树上的每条路径都被赋予了价值。具体地,这棵树上长度为 d d d 的简单路径的价值是 2 d 2^d 2d

现在 Ayano \text{Ayano} Ayano 对你发出了 q q q 次询问,每次给出两个正整数 x , y x,y x,y ,请你回答所有通过顶点 x x x y y y 的简单路径的价值之和 (   m o d     998244353 ) (\bmod\ 998244353) (mod 998244353)

注:简单路径是指路径上的各顶点均不互相重复的路径,路径的长度是指一条路径经过的边的条数。

n ≤ 1 0 6 n\le10^6 n106


d u d_u du 表示 u u u 1 1 1 的距离。

预处理出 s u m u = ∑ v ∈ T u 2 d v − d u sum_u=\sum\limits_{v\in T_{u}}2^{d_v-d_u} sumu=vTu2dvdu

考虑两种情况

  • x x x y y y 都不是 l c a lca lca。答案就是 2 dis ⁡ ( x , y ) ∑ u ∈ T x 2 d u − d x ∑ v ∈ T y 2 d v − d y 2^{\operatorname{dis}(x,y)}\sum\limits_{u\in T_x}2^{d_u-d_x}\sum\limits_{v\in T_y}2^{d_v-d_y} 2dis(x,y)uTx2dudxvTy2dvdy,直接用 s u m sum sum 求即可。
  • 否则,就要进行换根的操作,令 x x x 为深度小的那个点,我们想要求以 x x x 的儿子(往下走可以走到 y y y)为根的 s u m sum sum。简单维护即可。具体可以参照代码。

由于要求 l c a lca lca,我采用树剖的方法,其实可以用 tarjan,我不会。

这里要卡常。

时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

#include<bits/stdc++.h>
using namespace std;
constexpr int N=1e6+1;
constexpr long long mod=998244353ll;
int n,q;
int head[N],nxt[N<<1],to[N<<1],cnt;
int dep[N],sz[N],fa[N],top[N],son[N];
int sum[N],pw[N],sum1[N];
void add(int u,int v)
{
    to[++cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
}
inline int MOD(int x){return x>=mod?x-mod:x;}
void dfs1(int u,int F)
{
    dep[u]=dep[F]+1;
    fa[u]=F;
    sz[u]=1;
    for(int i=head[u];i;i=nxt[i]){
        if(to[i]!=F){
            dfs1(to[i],u);
            sz[u]+=sz[to[i]];
            if(sz[son[u]]<sz[to[i]]) son[u]=to[i];
            sum[u]=MOD(sum[u]+sum[to[i]]);
        }
    }
    sum[u]=MOD((sum[u]<<1)+1);
}
void dfs2(int u,int t)
{
    top[u]=t;
    if(son[u]) dfs2(son[u],t);
    for(int i=head[u];i;i=nxt[i]){
        if(to[i]!=fa[u]&&to[i]!=son[u]){
            dfs2(to[i],to[i]);
        }
    }
}
int lca(int u,int v)
{
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        u=fa[top[u]];
    }
    return dep[u]>dep[v]?v:u;
}
void dfs3(int u)
{
    int x=0;
    for(int i=head[u];i;i=nxt[i]) if(to[i]!=fa[u]) x=MOD(x+sum[to[i]]);
    for(int i=head[u];i;i=nxt[i]){
        if(to[i]!=fa[u]){
            sum1[to[i]]=MOD((MOD(MOD(x+sum1[u])+mod-sum[to[i]])<<1)+1);
            dfs3(to[i]);
        }
    }
}
int main()
{
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    cin.tie(0)->sync_with_stdio(0);
    cin>>n;
    for(int i=1,x,y;i<n;i++){
        cin>>x>>y;
        add(x,y),add(y,x);
    }
    pw[0]=1;
    for(int i=1;i<=n;i++) pw[i]=MOD(pw[i-1]<<1);
    dfs1(1,0);
    dfs2(1,1);
    dfs3(1);
    cin>>q;
    for(int i=1,x,y;i<=q;i++){
        cin>>x>>y;
        int Lca=lca(x,y);
        if(x!=Lca&&y!=Lca) cout<<1ll*sum[x]*sum[y]%mod*pw[dep[x]+dep[y]-2*dep[Lca]]%mod<<"\n";
        else{
            if(dep[x]>dep[y]) swap(x,y);
            int xx=dep[y]-dep[x]-1,now=y;
            if(xx>0){
                while(top[x]!=top[now]){
                    now=top[now];
                    if(fa[now]==x) goto a;
                    now=fa[now];
                }
                now=son[x];
            }
            a:cout<<1ll*sum[y]*sum1[now]%mod*pw[dep[x]+dep[y]-2*dep[Lca]]%mod<<"\n";
        }
    }
}

http://lihuaxi.xjx100.cn/news/1745806.html

相关文章

k8s之亲和性、污点

目录 亲和性 键值运算关系 硬策略 软策略 Pod亲和性与反亲和性 污点(Taint) 和 容忍(Tolerations) 污点(Taint) 容忍(Tolerations) 维护操作 故障排除步骤 亲和性 官方介绍&#xff1a;https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-nod…

pip install python是关于 NMake Makefiles报错

CMake Error at CMakeLists.txt:2 (PROJECT):GeneratorNMake Makefilesdoes not support platform specification, but platformx64was specified. I cant install opencv-python because I dont have vs? - Stack Overflow 这样解决就行。

scrapy+selenium框架模拟登录

目录 一、cookie和session实现登录原理 二、模拟登录方法-Requests模块Cookie实现登录 三、cookiesession实现登录并获取数据 四、selenium使用基本代码 五、scrapyselenium实现登录 一、cookie和session实现登录原理 cookie:1.网站持久保存在浏览器中的数据2.可以是长期…

数据结构与算法:使用数组模拟队列Java版

逻辑分析 代码实现 package com.haimeng.queue;import java.util.Scanner;public class ArrayQueueDemo {public static void main(String[] args) {//测试一把//创建一个队列ArrayQueue queue new ArrayQueue(3);char key ; //接收用户输入Scanner scanner new Scanner(S…

索引失效的场景有哪些?

虽然你这列上建了索引&#xff0c;查询条件也是索引列&#xff0c;但最终执行计划没有走它的索引。下面是引起这种问题的几个关键点。 列与列对比 某个表中&#xff0c;有两列&#xff08;id和c_id&#xff09;都建了单独索引&#xff0c;下面这种查询条件不会走索引 select…

HHDBCS扩展数据库类型

为应对市面上的数据库种类繁多的问题&#xff0c;HHDBCS设置了扩展数据库功能。 在登陆界面点击“工具”&#xff0c;选择“扩展数据库类型”&#xff1b; 注&#xff1a;HHDBCS支持已kingbase&#xff0c;本文仅用来举例。 填入名称、所需数据库的信息&#xff0c;上传驱动…

【【深入浅出了解AXI4协议 - 2】】

深入浅出了解AXI4协议 - 2 AXI总线共有五个通道 read address channel write address channel read data channel write data channel write response channel 信息源 通过VALID 信号 来指示 通道中的 数据和 控制信号 什么时候 有效 目的源 READY 表示何时接收数据 读数据 …

php 接口请求一次,controller调用了两次。

这几天开发一个数据导出功能 由于是数据导出&#xff0c;所以有点慢。然后发现一个问题&#xff0c;前端只请求一次&#xff0c;controller却收到了两次请求。而且第二次请求i必定失败 这就悲催了。脑子懵懵的&#xff01; 由于我这就是个小活儿&#xff0c;于是环境就是使用…