洛谷 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\) 的时代了吗?落伍了落伍了/ ...
随机推荐
- html5文本标签
标题文本 h1.h2.h3.h4.h5.h6 其中 h1.h2.h3是比较常用的.h3.h4.h5.h6相对来说用的会少一点,除非结构层次比较深才会使用. 段落文本 p <p>这是一个段落 ...
- HarmonyOS SDK让小红书鸿蒙用户尽享原生相机的拍摄之美
小红书是深受年轻人喜爱的生活社交类社区平台,越来越多的人在小红书上分享旅行.日常.心情.近日,不少使用鸿蒙原生版小红书的细心用户已经发现,直接使用小红书拍摄照片与自己使用原相机拍摄有一样清晰美观的呈现 ...
- AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
最近在研究AI Agent如何调用三方API,整理了一篇文章,分享给大家. 调用三方 API(Function Calling)不是通过提示词(Prompt)来实现的,而是通过函数调用机制(Funct ...
- 解决CondaError: Run 'conda init' before 'conda activate'
前言 使用 Anaconda 激活 python 环境,报错: conda activate deepseek7B CondaError: Run 'conda init' before 'conda ...
- go 编译约束//go:build dev //+build
前言 在真实环境中,我们可能需要为不同的编译环境编写不同的 Go 代码,所以需要做构建约束. 比如:syscall.NewLazyDLL("test.dll") 加载 dll 的程 ...
- 如何不购买域名在云服务器上搭建HTTPS服务
step 1: 事前准备 step 1.1: 云服务器 购买一台云服务器(带有弹性公网IP),阿里云,腾讯云,华为云什么的都可以. 选择ubuntu系统 开放安全组策略(把你需要的协议/端口暴露出来) ...
- Two-Stream Convolutional Networks for Action Recognition in Videos论文精读
Two-Stream Convolutional Networks for Action Recognition in Videos论文精读 大家好,今天我要讲的论文是一篇视频理解领域的开山之作,这是 ...
- layui table表格中点击图片放大
{field:'plateNoPicUri', title: '图片' ,width:"10%" ,templet:function(data){ if("" ...
- 二分查找--java进阶day06
1.二分查找 https://kdocs.cn/l/ciMkwngvaWfz?linkname=150996908 二分查找:每一次查找都从中间的元素查起,根据比较的大小来折半,以此类推,直到最后找到 ...
- 分享 3 款基于 .NET 开源且免费的远程桌面工具
前言 今天大姚给大家分享 3 款基于 .NET 开源.免费.功能强大的远程桌面工具,希望可以给大家的远程工作和学习带来便利. 1Remote 1Remote是一款基于 .NET 开源(GPL-3.0 ...