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
",ans[tmp]?"AYE":"NAY");
104     }
105     return 0;
106 }
原文地址:https://www.cnblogs.com/letlifestop/p/10453456.html