洛谷 P6626 [省选联考 2020 B 卷] 消息传递
洛谷 P6626 [省选联考 2020 B 卷] 消息传递
Problem
给一棵有\(n\)个节点的树。有\(m\)个询问,每次给出一对\(x,k\)表示查询到点\(x\)的距离为\(k\)的点有多少个。
\(T\)组数据。
\(1\sim3:1\le n,m\le10^3\\\)
\(4\sim6:1\le n,m\le 10^5,k\le 20\\\)
\(7\sim10:1\le n,m\le 10^5\\\)
\(\forall:1\le T\le5,1\le x\le n,0\le k\le n\).
Solution1
暴力不必多说,写个\(dfs/bfs\)就有\(30pts\),时间复杂度是\(O(n^2)\)。
优化
对点分治还不熟练,所以先来学个另类做法。
将询问离线,然后用换根法进行处理。
将根从\(x\)换为\(y\)时,\(y\)的子树中所有节点深度减一,其他点的深度都加一。用桶来记录深度。
先用树链剖分将树变为序列方便区间操作。
每一次换根,我们都需要做两次区间修改,同时还要维护一个桶。所以不能用线段树,但是可以用分块。对每个块开一个桶即可。
当换根到有询问的点时,暴力拿出对应块的桶进行计数即可。
时间复杂度\(O(Tn\sqrt n)\),空间复杂度\(O(n\sqrt n)\)。
理论可以通过,实际需要开\(O2\).
Code1
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<limits.h>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define debug printf("Now is %d\n",__LINE__);
using namespace std;
template<class T>inline void read(T& x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0'; ch=getchar();
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar(); }
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0'; ch=getchar();
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar(); }
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do { G[++g]=x%10; x/=10; } while(x);
for(int i=g; i>=1; --i)putchar('0'+G[i]); putchar('\n');
}
int T;
#define N 100010
#define M 400
//graph
int head[N],ver[N<<1],nxt[N<<1],cnt;
IL void insert(int x,int y)
{
nxt[++cnt]=head[x];
head[x]=cnt;
ver[cnt]=y;
nxt[++cnt]=head[y];
head[y]=cnt;
ver[cnt]=x;
}
//ask
struct node
{
int k,op,nxt;
}a[N];
int top;
int hh[N];
IL void insert(int x,int k,int op)
{
a[++top].k=k;
a[top].op=op;
a[top].nxt=hh[x];
hh[x]=top;
}
//pre
int dis[N],sze[N],dfn[N],dfncnt,m,n;
int b[N];
void dfs(int x,int f)
{
dis[x]=dis[f]+1;
sze[x]=1;
dfn[x]=++dfncnt;
b[dfncnt]=dis[x];
for(int i=head[x];i;i=nxt[i])
{
if(ver[i]==f) continue;
dfs(ver[i],x);
sze[x]+=sze[ver[i]];
}
}
//block
int len,s;
int L[M],R[M],belong[N];
int lazy[M],c[M][N];
void change(int x,int y,int v)
{
re int xx=belong[x],yy=belong[y],i,j;
if(xx==yy)
{
for(i=L[xx];i<=R[xx];i++)
{
c[xx][b[i]]--;
b[i]+=lazy[xx];
}
lazy[xx]=0;
for(i=x;i<=y;i++)
{
b[i]+=v;
}
for(i=L[xx];i<=R[xx];i++)
{
c[xx][b[i]]++;
}
}
else
{
for(i=xx+1;i<=yy-1;i++)
{
lazy[i]+=v;
}
for(i=L[xx];i<=R[xx];i++)
{
c[xx][b[i]]--;
b[i]+=lazy[xx];
}
for(i=L[yy];i<=R[yy];i++)
{
c[yy][b[i]]--;
b[i]+=lazy[yy];
}
lazy[xx]=lazy[yy]=0;
for(i=x;i<=R[xx];i++)
{
b[i]+=v;
}
for(i=L[yy];i<=y;i++)
{
b[i]+=v;
}
for(i=L[xx];i<=R[xx];i++)
{
c[xx][b[i]]++;
}
for(i=L[yy];i<=R[yy];i++)
{
c[yy][b[i]]++;
}
}
}
int ans[N];
void dfs1(int x,int f)
{
re int i,j;
for(i=hh[x];i;i=a[i].nxt)
{
for(j=1;j<=s;j++)
{
if(a[i].k+1-lazy[j]>=0) ans[a[i].op]+=c[j][a[i].k+1-lazy[j]];
}
}
for(i=head[x];i;i=nxt[i])
{
if(ver[i]==f) continue;
for(j=1;j<=s;j++) lazy[j]++;
change(dfn[ver[i]],dfn[ver[i]]+sze[ver[i]]-1,-2);
dfs1(ver[i],x);
for(j=1;j<=s;j++) lazy[j]--;
change(dfn[ver[i]],dfn[ver[i]]+sze[ver[i]]-1,2);
}
}
int main()
{
T=read();
int i,j,x,k;
while(T--)
{
//init
memset(head,0,sizeof(head));cnt=0;
memset(hh,0,sizeof(hh));top=0;
dfncnt=0;
memset(lazy,0,sizeof(lazy));
memset(ans,0,sizeof(ans));
//work
n=read();
m=read();
for(i=1;i<n;i++) insert(read(),read());
dfs(1,0);
for(i=1;i<=m;i++)
{
x=read();
k=read();
insert(x,k,i);
}
len=sqrt(n);
s=n/len;
for(i=1;i<=s;i++)
{
L[i]=n/s*(i-1)+1;
R[i]=n/s*i;
}
R[s]=n;
for(i=1;i<=s;i++)
{
for(int j=L[i];j<=R[i];j++)
{
belong[j]=i;
}
}
for(i=1;i<=s;i++)
{
lazy[i]=0;
for(int j=L[i];j<=R[i];j++)
{
c[i][b[j]]++;
}
}
dfs1(1,0);
for(i=1;i<=m;i++) cout<<ans[i]<<endl;
for(i=1;i<=s;i++)
{
lazy[i]=0;
for(j=L[i];j<=R[i];j++)
{
c[i][b[j]]=0;
}
}
}
return 0;
}
Solution2
再看题目像点分治,但是这里指定了目标点。
猜想把询问离线,那就考虑怎么分别计算贡献。
Code2
洛谷 P6626 [省选联考 2020 B 卷] 消息传递的更多相关文章
- 洛谷P6623——[省选联考 2020 A 卷] 树
传送门:QAQQAQ 题意:自己看 思路:正解应该是线段树/trie树合并? 但是本蒟蒻啥也不会,就用了树上二次差分 (思路来源于https://www.luogu.com.cn/blog/dengy ...
- 洛谷 P6624 - [省选联考 2020 A 卷] 作业题(矩阵树定理+简单数论)
题面传送门 u1s1 这种题目还是相当套路的罢 首先看到 \(\gcd\) 可以套路地往数论方向想,我们记 \(f_i\) 为满足边权的 \(\gcd\) 为 \(i\) 的倍数的所有生成树的权值之和 ...
- [题解] LOJ 3300 洛谷 P6620 [省选联考 2020 A 卷] 组合数问题 数学,第二类斯特林数,下降幂
题目 题目里要求的是: \[\sum_{k=0}^n f(k) \times X^k \times \binom nk \] 这里面出现了给定的多项式,还有组合数,这种题目的套路就是先把给定的普通多项 ...
- 洛谷 P7520 - [省选联考 2021 A 卷] 支配(支配树)
洛谷题面传送门 真·支配树不 sb 的题. 首先题面已经疯狂暗示咱们建出支配树对吧,那咱就老老实实建呗.由于这题数据范围允许 \(n^2\) 算法通过,因此可以考虑 \(\mathcal O(n^2 ...
- 洛谷 P7515 - [省选联考 2021 A 卷] 矩阵游戏(差分约束)
题面传送门 emmm--怎么评价这个题呢,赛后学完差分约束之后看题解感觉没那么 dl,可是现场为啥就因为种种原因想不到呢?显然是 wtcl( 先不考虑"非负"及" \(\ ...
- [省选联考 2020 A 卷] 组合数问题
题意 [省选联考 2020 A 卷] 组合数问题 想法 自己在多项式和数论方面还是太差了,最近写这些题都没多少思路,看完题解才会 首先有这两个柿子 \(k*\dbinom{n}{k} = n*\dbi ...
- luoguP6623 [省选联考 2020 A 卷] 树(trie树)
luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...
- luoguP6620 [省选联考 2020 A 卷] 组合数问题(斯特林数)
luoguP6620 [省选联考 2020 A 卷] 组合数问题(斯特林数) Luogu 题外话: LN切这题的人比切T1的多. 我都想到了组合意义乱搞也想到可能用斯特林数为啥还是没做出来... 我怕 ...
- luoguP6624 [省选联考 2020 A 卷] 作业题(莫比乌斯反演,矩阵树定理)
luoguP6624 [省选联考 2020 A 卷] 作业题(莫比乌斯反演,矩阵树定理) Luogu 题外话: Day2一题没切. 我是傻逼. 题解时间 某种意义上说刻在DNA里的柿子,大概是很多人学 ...
- 洛谷 P7516 - [省选联考 2021 A/B 卷] 图函数(Floyd)
洛谷题面传送门 一道需要发现一些简单的性质的中档题(不过可能这道题放在省选 D1T3 中偏简单了?) u1s1 现在已经是 \(1\text{s}\) \(10^9\) 的时代了吗?落伍了落伍了/ ...
随机推荐
- Open-Sora 2.0 重磅开源!
潞晨科技正式推出 Open-Sora 2.0 -- 一款全新开源的 SOTA 视频生成模型,仅 20 万美元(224 张 GPU)成功训练商业级 11B 参数视频生成大模型.开发高性能的视频生成模型通 ...
- CNVD挖掘思路
CNVD挖掘思路 CNVD获取条件 首先,先来了解一下目前cnvd发证资格 1.事件型 事件型漏洞必须是三大运营商(移动.联通.电信)的中高危漏洞,或者党政机关.重要行业单位.科研院所.重要企事业单位 ...
- Ubuntu Nvidia driver驱动安装(新)
前言 英伟达更新了安装驱动的方式,更新一下文档 旧文:Ubuntu Nvidia driver驱动安装及卸载 下载官方驱动安装 1.安装驱动前一定要更新软件列表和安装必要软件.依赖(必须) sudo ...
- gorm中使用乐观锁
乐观锁简介 乐观锁(又称乐观并发控制)是一种常见的数据库并发控制策略. 乐观并发控制多数用于数据竞争(data race)不大.冲突较少的环境中,这种环境中,偶尔回滚事务的成本会低于读取数据时锁定数据 ...
- linux php安装mongodb 扩展
下载扩展 首先从这个网站选择适合你当前 php 版本的的 mongodb 扩展 https://pecl.php.net/package/mongodb wget https://pecl.php.n ...
- 从 PostgreSQL 升级至 IvorySQL 4.0
本文作者:严少安,IvorySQL 贡献者. 本文为授权转载. 2024 年 8 月,我在<PG 12 即将退役,建议升级到 16.4>一文中提到,PostgreSQL 12 版本即将&q ...
- 关于DevExpress VCL汉化方法
用法1:在工程中加入控件cxLocalizer; 在程序中加入如下语句: Localizer.LoadFromFile('DevLocal.ini'); Localizer.Language := ' ...
- panic: qtls.ConnectionState not compatible with tls.ConnectionState
问题重现 之前一个 go-micro 1.18 的项目 执行 go run main.go 命令时出现以下报错 go run main.go panic: qtls.ConnectionState n ...
- 阿里云ECS下安装的MySQL无法远程连接?
场景重现 在阿里云ECS下, Ubuntu系统上通过以下命令安装的MySQL数据库, 本地连接正常, 但远程死活连接不上. # 安装MySQL apt-get install mysql-server ...
- Armbian安装防火墙软件
在Armbian操作系统中安装防火墙是一项提升系统安全性的重要步骤.Armbian是一个针对ARM架构设备的Debian Linux发行版,它广泛应用于各类ARM开发板和单板计算机上.下面将具体展开讲 ...