P3806 【模板】点分治1(CDQ分治)
题目链接:https://www.luogu.org/problemnew/show/P3806
题目大意:中文题目
具体思路:直接dfs好像会超时,然后我们就开始想优化的方法,然后就是一个CDQ入门题了,我们可以分解成许多子问题进行解决,然后对于一棵树的话,我们最好的切入点就是这棵树的重心了,这样就能使得复杂度尽可能的低了,然后就不停的往下递归找每一棵子树的重心进行求解就可以了,然后注意去重。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 # define inf 0x3f3f3f3f 5 const int maxn = 1e6+100; 6 # define inf 0x3f3f3f3f 7 struct node 8 { 9 int to; 10 int nex; 11 int cost; 12 } edge[maxn<<2]; 13 int head[maxn<<2],num=0; 14 int dis[maxn],ans[maxn],mx[maxn]; 15 int S,root; 16 int Size[maxn],vis[maxn]; 17 int n,m,tot=0; 18 void addedge(int fr,int to,int cost) 19 { 20 edge[num].to=to; 21 edge[num].cost=cost; 22 edge[num].nex=head[fr]; 23 head[fr]=num++; 24 } 25 void Find(int x,int rt) 26 { 27 Size[x]=1; 28 mx[x]=0; 29 for(int i=head[x]; i!=-1; i=edge[i].nex) 30 { 31 int to=edge[i].to; 32 if(to==rt||vis[to]) 33 continue; 34 Find(to,x); 35 Size[x]+=Size[to]; 36 mx[x]=max(mx[x],Size[to]); 37 } 38 mx[x]=max(mx[x],S-Size[x]); 39 if(mx[x]<mx[root]) 40 root=x; 41 } 42 int a[maxn]; 43 void get_dis(int x,int len,int rt) 44 { 45 dis[++tot]=a[x]; 46 for(int i=head[x]; i!=-1; i=edge[i].nex) 47 { 48 int to=edge[i].to; 49 if(to==rt||vis[to]) 50 continue; 51 a[to]=len+edge[i].cost; 52 get_dis(to,len+edge[i].cost,x); 53 } 54 } 55 void solve(int x,int len,int w) 56 { 57 tot=0; 58 a[x]=len; 59 get_dis(x,len,0); 60 for(int i=1; i<=tot; i++) 61 { 62 for(int j=1; j<=tot; j++) 63 { 64 if(i==j) 65 continue; 66 ans[dis[i]+dis[j]]+=w; 67 } 68 } 69 } 70 void divide(int x) 71 { 72 solve(x,0,1); 73 vis[x]=1; 74 for(int i=head[x]; i!=-1; i=edge[i].nex) 75 { 76 int to=edge[i].to; 77 if(vis[to]) 78 continue; 79 solve(to,edge[i].cost,-1);//去重 80 S=Size[x],root=0,mx[0]=Size[x]; 81 Find(to,x); 82 divide(root); 83 } 84 } 85 int main() 86 { 87 memset(head,-1,sizeof(head)); 88 scanf("%d %d",&n,&m); 89 int st,ed,cost; 90 for(int i=1; i<n; i++) 91 { 92 scanf("%d %d %d",&st,&ed,&cost); 93 addedge(st,ed,cost); 94 addedge(ed,st,cost); 95 } 96 S=n,root=0,mx[0]=n; 97 Find(1,0); 98 divide(root); 99 int tmp; 100 for(int i=1; i<=m; i++) 101 { 102 scanf("%d",&tmp); 103 printf("%s\n",ans[tmp]?"AYE":"NAY"); 104 } 105 return 0; 106 }