zoukankan      html  css  js  c++  java
  • 点分治

    点分治

    树结构

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

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

    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 */
  • 相关阅读:
    优先队列总结
    CodeForces 567D One-Dimensional Battle Ships
    CodeForces 567D One-Dimensional Battle Ships
    codeforces 1016B. Segment Occurrences
    codeforces 1016B. Segment Occurrences
    poj3249(求最长路)
    poj3249(求最长路)
    poj 2186
    2017年第八蓝桥杯C/C++ A组国赛 —— 第二题:生命游戏
    Fence Repair POJ
  • 原文地址:https://www.cnblogs.com/cmyg/p/10727078.html
Copyright © 2011-2022 走看看