点分治

点分治

树结构

可以被分成两半求,再合起来的

求路径长度,满足某些特性的字符/数

P3806 【模板】点分治1

用father数组,判断从一个点出发访问另外一个点(另外一个点是否访问,另外一个点是否是这个点的父亲)

clrdist 减少重复部分

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <set>
  8 #include <map>
  9 #include <queue>
 10 #include <iostream>
 11 using namespace std;
 12 
 13 #define ll long long
 14 
 15 const int maxn=1e4+10;
 16 const int maxq=1e2+10;
 17 const int maxvalue=1e7+10;
 18 const int inf=1e9;
 19 const double eps=1e-8;
 20 
 21 /*
 22 找重心
 23 子树再找重心
 24 根,子树(s) 间的操作
 25 可能要除去单个子树内两个结点的重复
 26 */
 27 
 28 struct node
 29 {
 30     int d,len;
 31     node *to;
 32 }*e[maxn];
 33 
 34 ll sum[maxq];   ///in case
 35 int query[maxq],siz[maxn],q,nn;
 36 int curroot,mins,clrdist[maxn],fa[maxn];
 37 int exist[maxvalue];
 38 bool has[maxn];
 39 
 40 void dfs(int d)
 41 {
 42     int dd,maxsiz=0;
 43     siz[d]=1;
 44     node *p=e[d];
 45     while (p)
 46     {
 47         dd=p->d;
 48         if (fa[d]!=dd && !has[dd])
 49         {
 50             fa[dd]=d;
 51             dfs(dd);
 52             maxsiz=max(maxsiz,siz[dd]);
 53             siz[d]+=siz[dd];
 54         }
 55         p=p->to;
 56     }
 57     maxsiz=max(maxsiz,nn-siz[d]);
 58     if (maxsiz<mins)
 59         mins=maxsiz,curroot=d;
 60 }
 61 
 62 void finddist(int d,int dis)
 63 {
 64     int dd;
 65     clrdist[++clrdist[0]]=dis;
 66     node *p=e[d];
 67     while (p)
 68     {
 69         dd=p->d;
 70         if (fa[d]!=dd && !has[dd])
 71             finddist(dd,dis+p->len);
 72         p=p->to;
 73     }
 74 }
 75 
 76 void work(int d)
 77 {
 78     int root,dd,i,j,preind,firind;
 79     firind=clrdist[0];
 80     mins=inf;   ///10000 * 10000
 81     nn=siz[d],dfs(d);
 82     root=curroot;
 83     has[root]=1;
 84     if (d!=root)
 85         siz[d]=nn-siz[root];    ///
 86 
 87     node *p=e[root];
 88     while (p)
 89     {
 90         dd=p->d;
 91         if (!has[dd])
 92         {
 93             work(dd);
 94             preind=clrdist[0];
 95             finddist(dd,p->len);
 96             for (i=preind+1;i<=clrdist[0];i++)
 97                 exist[clrdist[i]]++;
 98 
 99             for (i=preind+1;i<=clrdist[0];i++)
100                 for (j=1;j<=q;j++)
101                     if (query[j]>clrdist[i])
102                         sum[j]-=exist[clrdist[i]]*exist[query[j]-clrdist[i]];
103 
104             for (i=preind+1;i<=clrdist[0];i++)
105                 exist[clrdist[i]]--;
106 
107         }
108         p=p->to;
109     }
110 
111     for (i=firind+1;i<=clrdist[0];i++)
112         exist[clrdist[i]]++;
113 
114     for (i=firind+1;i<=clrdist[0];i++)
115         for (j=1;j<=q;j++)
116             if (query[j]>=clrdist[i])
117                 sum[j]+=exist[clrdist[i]]*exist[query[j]-clrdist[i]];
118     ///这里多算了
119     ///v+v=query[i] -exist[v]
120     ///相同的只要计算一次exist[v](重复多次)*exist[query[i]-v]
121     ///exist[p]*exist[q] exist[q]*exist[p] 重复
122 
123     for (i=firind+1;i<=clrdist[0];i++)
124         exist[clrdist[i]]--;
125     clrdist[0]=firind;
126 
127     has[root]=0;    ///取消不能走的限制
128 }
129 
130 int main()
131 {
132     node *p;
133     int n,i,a,b,c;
134     scanf("%d%d",&n,&q);
135     for (i=1;i<n;i++)
136     {
137         scanf("%d%d%d",&a,&b,&c);
138         p=new node();
139         p->d=b;
140         p->len=c;
141         p->to=e[a];
142         e[a]=p;
143 
144         p=new node();
145         p->d=a;
146         p->len=c;
147         p->to=e[b];
148         e[b]=p;
149     }
150     for (i=1;i<=q;i++)
151         scanf("%d",&query[i]);
152 
153     exist[0]=1;
154     siz[1]=n,work(1);
155 
156     for (i=1;i<=q;i++)
157         if (sum[i]==0)
158             printf("NAY
");
159         else
160             printf("AYE
");
161     return 0;
162 }
163 /*
164 6 15
165 1 2 2
166 1 3 3
167 2 6 3
168 3 4 1
169 3 5 2
170 1
171 2
172 3
173 4
174 5
175 6
176 7
177 8
178 9
179 10
180 11
181 12
182 13
183 14
184 15
185 
186 6 15
187 1 2 1
188 1 3 3
189 1 4 4
190 1 5 7
191 5 6 1
192 1
193 2
194 3
195 4
196 5
197 6
198 7
199 8
200 9
201 10
202 11
203 12
204 13
205 14
206 15
207 */

用了vis数组,每次使用需要初始化,不太方便

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <set>
  8 #include <map>
  9 #include <queue>
 10 #include <iostream>
 11 using namespace std;
 12 
 13 #define ll long long
 14 
 15 const int maxn=1e4+10;
 16 const int maxq=1e2+10;
 17 const int maxvalue=1e7+10;
 18 const int inf=1e9;
 19 const double eps=1e-8;
 20 
 21 /*
 22 找重心
 23 子树再找重心
 24 根,子树(s) 间的操作
 25 可能要除去单个子树内两个结点的重复
 26 */
 27 
 28 struct node
 29 {
 30     int d,len;
 31     node *to;
 32 }*e[maxn];
 33 
 34 ll sum[maxq];   ///in case
 35 int query[maxq],siz[maxn],q,nn;
 36 int curroot,mins,clrvis[maxn],clrdist[maxn];
 37 int exist[maxvalue];
 38 bool has[maxn],vis[maxn];
 39 
 40 void dfs(int d)
 41 {
 42     int dd,maxsiz=0;
 43     siz[d]=1;
 44     clrvis[++clrvis[0]]=d;
 45     vis[d]=1;
 46     node *p=e[d];
 47     while (p)
 48     {
 49         dd=p->d;
 50         if (!vis[dd] && !has[dd])
 51         {
 52             dfs(dd);
 53             maxsiz=max(maxsiz,siz[dd]);
 54             siz[d]+=siz[dd];
 55         }
 56         p=p->to;
 57     }
 58     maxsiz=max(maxsiz,nn-siz[d]);
 59     if (maxsiz<mins)
 60         mins=maxsiz,curroot=d;
 61 }
 62 
 63 void finddist(int d,int dis)
 64 {
 65     int dd;
 66     clrvis[++clrvis[0]]=d;
 67     vis[d]=1;
 68     clrdist[++clrdist[0]]=dis;
 69     node *p=e[d];
 70     while (p)
 71     {
 72         dd=p->d;
 73         if (!vis[dd] && !has[dd])
 74             finddist(dd,dis+p->len);
 75         p=p->to;
 76     }
 77 }
 78 
 79 void work(int d)
 80 {
 81     int root,dd,i,j,preind,firind;
 82     firind=clrdist[0];
 83     mins=inf;   ///10000 * 10000
 84     nn=siz[d],dfs(d);
 85     for (i=1;i<=clrvis[0];i++)
 86         vis[clrvis[i]]=0;
 87     clrvis[0]=0;
 88     root=curroot;
 89     has[root]=1;
 90     if (d!=root)
 91         siz[d]=nn-siz[root];    ///
 92 
 93     node *p=e[root];
 94     while (p)
 95     {
 96         dd=p->d;
 97         if (!has[dd])
 98         {
 99             work(dd);
100             preind=clrdist[0];
101             finddist(dd,p->len);
102             for (i=1;i<=clrvis[0];i++)
103                 vis[clrvis[i]]=0;
104             clrvis[0]=0;
105 
106             for (i=preind+1;i<=clrdist[0];i++)
107                 exist[clrdist[i]]++;
108 
109             for (i=preind+1;i<=clrdist[0];i++)
110                 for (j=1;j<=q;j++)
111                     if (query[j]>clrdist[i])
112                         sum[j]-=exist[clrdist[i]]*exist[query[j]-clrdist[i]];
113 
114             for (i=preind+1;i<=clrdist[0];i++)
115                 exist[clrdist[i]]--;
116 
117         }
118         p=p->to;
119     }
120 
121     for (i=firind+1;i<=clrdist[0];i++)
122         exist[clrdist[i]]++;
123 
124     for (i=firind+1;i<=clrdist[0];i++)
125         for (j=1;j<=q;j++)
126             if (query[j]>=clrdist[i])
127                 sum[j]+=exist[clrdist[i]]*exist[query[j]-clrdist[i]];
128     ///这里多算了
129     ///v+v=query[i] -exist[v]
130     ///相同的只要计算一次exist[v](重复多次)*exist[query[i]-v]
131     ///exist[p]*exist[q] exist[q]*exist[p] 重复
132 
133     for (i=firind+1;i<=clrdist[0];i++)
134         exist[clrdist[i]]--;
135     clrdist[0]=firind;
136 
137     has[root]=0;    ///取消不能走的限制
138 }
139 
140 int main()
141 {
142     node *p;
143     int n,i,a,b,c;
144     scanf("%d%d",&n,&q);
145     for (i=1;i<n;i++)
146     {
147         scanf("%d%d%d",&a,&b,&c);
148         p=new node();
149         p->d=b;
150         p->len=c;
151         p->to=e[a];
152         e[a]=p;
153 
154         p=new node();
155         p->d=a;
156         p->len=c;
157         p->to=e[b];
158         e[b]=p;
159     }
160     for (i=1;i<=q;i++)
161         scanf("%d",&query[i]);
162 
163     exist[0]=1;
164     siz[1]=n,work(1);
165 
166     for (i=1;i<=q;i++)
167         if (sum[i]==0)
168             printf("NAY
");
169         else
170             printf("AYE
");
171     return 0;
172 }
173 /*
174 6 15
175 1 2 2
176 1 3 3
177 2 6 3
178 3 4 1
179 3 5 2
180 1
181 2
182 3
183 4
184 5
185 6
186 7
187 8
188 9
189 10
190 11
191 12
192 13
193 14
194 15
195 
196 6 15
197 1 2 1
198 1 3 3
199 1 4 4
200 1 5 7
201 5 6 1
202 1
203 2
204 3
205 4
206 5
207 6
208 7
209 8
210 9
211 10
212 11
213 12
214 13
215 14
216 15
217 */
原文地址:https://www.cnblogs.com/cmyg/p/10727078.html