[luogu P3806] 模板点分治1
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu P3806] 模板点分治1相关的知识,希望对你有一定的参考价值。
[luogu P3806] 【模板】点分治1
题目背景
感谢hzwer的点分治互测。
题目描述
给定一棵有n个点的树
询问树上距离为k的点对是否存在。
输入输出格式
输入格式:
n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径
接下来m行每行询问一个K
输出格式:
对于每个K每行输出一个答案,存在输出“AYE”,否则输出”NAY”(不包含引号)
输入输出样例
说明
对于30%的数据n<=100
对于60%的数据n<=1000,m<=50
对于100%的数据n<=10000,m<=100,c<=1000,K<=10000000
首先这是点分裸题啊。。刷过点分的dalao都知道。
但似乎这题我只会calc里面n^2暴力扫?用不来m的100?
没事,让我们证明一下复杂度。。
T(n)=2T(n/2)+n^2。
然后我并不会主定理。。画了下二叉树图。
然后发现T(n)=2n^2(n^2+(1/2)n^2+(1/4)n^2+...)。
然后,因为n=10000,把常数写小一点,有点信仰就可以了。
code:
View Code1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define ms(a,x) memset(a,x,sizeof a) 5 using namespace std; 6 const int N=10005,D=10000005; 7 int n,tot,lnk[N],nxt[N<<1],son[N<<1],w[N<<1]; 8 int ro,subn,cnt,siz[N],mxs[N],dep[N],d[N]; 9 int m,c[D]; bool vis[N]; 10 void add (int x,int y,int z) { 11 nxt[++tot]=lnk[x],lnk[x]=tot; 12 son[tot]=y,w[tot]=z; 13 } 14 void dfs_size(int x,int p) { 15 siz[x]=1,mxs[x]=0; 16 for (int j=lnk[x]; j; j=nxt[j]) { 17 if (son[j]==p||vis[son[j]]) continue; 18 dfs_size(son[j],x); 19 siz[x]+=siz[son[j]]; 20 if (mxs[x]<siz[son[j]]) mxs[x]=siz[son[j]]; 21 } 22 if (mxs[x]<subn-mxs[x]) mxs[x]=subn-mxs[x]; 23 if (mxs[x]<mxs[ro]) ro=x; 24 } 25 void dfs_depth (int x,int p) { 26 dep[++cnt]=d[x]; 27 for (int j=lnk[x]; j; j=nxt[j]) { 28 if (son[j]==p||vis[son[j]]) continue; 29 d[son[j]]=d[x]+w[j]; 30 dfs_depth(son[j],x); 31 } 32 } 33 void calc (int x,int v) { 34 cnt=0,dfs_depth(x,0); 35 for (int i=1; i<cnt; ++i) { 36 for (int j=i+1; j<=cnt; ++j) { 37 c[dep[i]+dep[j]]+=v; 38 } 39 } 40 } 41 void node_divide (int x) { 42 ro=0,dfs_size(x,0),vis[ro]=1; 43 d[ro]=0,calc(ro,1); 44 for (int j=lnk[ro]; j; j=nxt[j]) { 45 if (vis[son[j]]) continue; 46 calc(son[j],-1); 47 subn=siz[son[j]]; 48 node_divide(son[j]); 49 } 50 } 51 int main() { 52 int x,y,z; 53 scanf("%d%d",&n,&m); 54 for (int i=1; i<n; ++i) { 55 scanf("%d%d%d",&x,&y,&z); 56 add(x,y,z),add(y,x,z); 57 } 58 ro=0,mxs[0]=n,subn=n; 59 node_divide(1); 60 for (int i=1; i<=m; ++i) { 61 scanf("%d",&x); 62 printf("%s\n",c[x]>0?"AYE":"NAY"); 63 } 64 return 0; 65 }
以上是关于[luogu P3806] 模板点分治1的主要内容,如果未能解决你的问题,请参考以下文章