zoukankan      html  css  js  c++  java
  • 树分治入门:例题poj1741

    题目链接:Tree

    树分治参考资料:09年漆子超  ZigZagK的博客 【点分治】的学习笔记和众多例题

    以上的资料是我看过好的,具体算法分析实现都讲明白.

     1 //#include<bits/stdc++.h>
     2 #include<set>
     3 #include<cstdio>
     4 #include<iomanip>
     5 #include<iostream>
     6 #include<string>
     7 #include<cstring>
     8 #include<algorithm>
     9 #define pb push_back
    10 #define ll long long
    11 #define fi first
    12 #define se second
    13 #define PI 3.14159265
    14 #define ls l,m,rt<<1
    15 #define rs m+1,r,rt<<1|1
    16 #define eps 1e-7
    17 #define pii pair<int,int>
    18 typedef unsigned long long ull;
    19 const int mod=1e3+5;
    20 const ll inf=0x3f3f3f3f3f3f3f;
    21 const int maxn=1e5+5;
    22 using namespace std;
    23 int n,m,head[maxn],to[maxn*2],w[maxn*2],nxt[maxn*2],cnt,k,siz[maxn],dep[maxn],rt,mx[maxn],s;
    24 int now[maxn];
    25 bool vis[maxn];
    26 ll ans;
    27 void add_edge(int x,int y,int l)
    28 {
    29     to[++cnt]=y;w[cnt]=l;nxt[cnt]=head[x];head[x]=cnt;
    30 }
    31 void dfs_rt(int v,int f)//找重心
    32 {
    33     siz[v]=1;mx[v]=0;
    34     //cout<<v<<"SSS"<<f<<endl;
    35     for(int i=head[v];i;i=nxt[i])
    36     {
    37         if(to[i]==f||vis[to[i]])continue;
    38         dfs_rt(to[i],v);
    39         siz[v]+=siz[to[i]];
    40         mx[v]=max(siz[to[i]],mx[v]);
    41     }
    42     mx[v]=max(s-siz[v],mx[v]);
    43     if(rt==-1||mx[v]<mx[rt])rt=v;
    44 }
    45 void get_dep(int v,int f)
    46 {
    47     now[++now[0]]=dep[v];
    48     for(int i=head[v];i;i=nxt[i])
    49     {
    50         if(vis[to[i]]||to[i]==f)continue;
    51         dep[to[i]]=dep[v]+w[i];
    52         get_dep(to[i],v);
    53     }
    54 }
    55 int  get_sum(int v,int dis)
    56 {
    57     int cn=0;now[0]=0;
    58     dep[v]=dis;get_dep(v,-1);
    59     sort(now+1,now+1+now[0]);
    60     int l=1,r=now[0];
    61     while(l<r)if(now[l]+now[r]<=k)cn+=r-l,l++;else r--;
    62     return cn;
    63 }
    64 void get_ans(int v)
    65 {
    66     vis[v]=true;ans+=get_sum(v,0);
    67     for(int i=head[v];i;i=nxt[i])
    68     {
    69         if(vis[to[i]])continue;
    70         ans-=get_sum(to[i],w[i]);
    71         rt=-1;s=siz[to[i]];dfs_rt(to[i],v);
    72         get_ans(rt);
    73     }
    74 }
    75 int main()
    76 {
    77     while(~scanf("%d %d",&n,&k))
    78     {
    79         if(!n&&!k)break;
    80         memset(head,0,sizeof(head));cnt=0;ans=0;
    81         memset(vis,0,sizeof(vis));
    82         for(int i=0;i<n-1;i++)
    83         {
    84             int u,v,l;
    85             scanf("%d %d %d",&u,&v,&l);
    86             add_edge(u,v,l);add_edge(v,u,l);
    87         }
    88         rt=-1;s=n;dfs_rt(1,-1);
    89         get_ans(rt);
    90         printf("%lld
    ",ans);
    91     }
    92     return 0;
    93 }

    第二个例题:2152: 聪聪可可

    题解:跟上面那题差不多,计算出的到根的距离%3之后的值的个数,now[0],now[1],now[2].答案就是now[0]*now[0]+2*now[1]*now[2]

     1 #include<bits/stdc++.h>
     2 #include<set>
     3 #include<cstdio>
     4 #include<iomanip>
     5 #include<iostream>
     6 #include<string>
     7 #include<cstring>
     8 #include<algorithm>
     9 #define pb push_back
    10 #define ll long long
    11 #define fi first
    12 #define se second
    13 #define PI 3.14159265
    14 #define ls l,m,rt<<1
    15 #define rs m+1,r,rt<<1|1
    16 #define eps 1e-7
    17 #define pii pair<int,int>
    18 typedef unsigned long long ull;
    19 const int mod=1e3+5;
    20 const ll inf=0x3f3f3f3f3f3f3f;
    21 const int maxn=2e4+5;
    22 using namespace std;
    23 int n,m,head[maxn],to[maxn*2],w[maxn*2],nxt[maxn*2],cnt,k,siz[maxn],dep[maxn],rt,mx[maxn],s;
    24 int now[maxn];
    25 bool vis[maxn];
    26 int ans;
    27 void add_edge(int x,int y,int l)
    28 {
    29     to[++cnt]=y;w[cnt]=l;nxt[cnt]=head[x];head[x]=cnt;
    30 }
    31 void dfs_rt(int v,int f)//找重心
    32 {
    33     siz[v]=1;mx[v]=0;
    34     for(int i=head[v];i;i=nxt[i])
    35     {
    36         if(to[i]==f||vis[to[i]])continue;
    37         dfs_rt(to[i],v);
    38         siz[v]+=siz[to[i]];
    39         mx[v]=max(siz[to[i]],mx[v]);
    40     }
    41     mx[v]=max(s-siz[v],mx[v]);
    42     if(rt==-1||mx[v]<mx[rt])rt=v;
    43 }
    44 void get_dep(int v,int f)
    45 {
    46     now[(dep[v])%3]++;
    47     for(int i=head[v];i;i=nxt[i])
    48     {
    49         if(vis[to[i]]||to[i]==f)continue;
    50         dep[to[i]]=dep[v]+w[i];
    51         get_dep(to[i],v);
    52     }
    53 }
    54 int  get_sum(int v,int dis)
    55 {
    56     int cn=0;now[0]=0,now[1]=0,now[2]=0;
    57     dep[v]=dis;get_dep(v,-1);
    58     cn+=now[0]*now[0]+2*now[1]*now[2];
    59     return cn;
    60 }
    61 void get_ans(int v)
    62 {
    63     vis[v]=true;ans+=get_sum(v,0);
    64     for(int i=head[v];i;i=nxt[i])
    65     {
    66         if(vis[to[i]])continue;
    67         ans-=get_sum(to[i],w[i]);
    68         rt=-1;s=siz[to[i]];dfs_rt(to[i],v);
    69         get_ans(rt);
    70     }
    71 }
    72 int main()
    73 {
    74     while(~scanf("%d",&n))
    75     {
    76         memset(head,0,sizeof(head));cnt=0;
    77         memset(vis,0,sizeof(vis));
    78         for(int i=0;i<n-1;i++)
    79         {
    80             int u,v,l;
    81             scanf("%d %d %d",&u,&v,&l);
    82             add_edge(u,v,l);add_edge(v,u,l);
    83         }
    84         rt=-1;s=n;dfs_rt(1,-1);
    85         get_ans(rt);
    86         int sum=n*n;
    87         int tmp=__gcd(sum,ans);
    88 
    89         ans/=tmp;sum/=tmp;
    90         printf("%d/%d
    ",ans,sum);
    91     }
    92     return 0;
    93 }
    View Code

    第三个题: 1316: 树上的询问

    在一次树分治的过程中统计到重心的距离,对于每一个q[i]枚举一个点然后二分去找q[i]-dep[i]的个数用lower_bound 和upper_bound相减就可以来。10sec.我9988ms卡过,,,,运气不好就t了

      1 #include<bits/stdc++.h>
      2 #include<set>
      3 #include<cstdio>
      4 #include<iomanip>
      5 #include<iostream>
      6 #include<string>
      7 #include<cstring>
      8 #include<algorithm>
      9 #define pb push_back
     10 #define ll long long
     11 #define fi first
     12 #define se second
     13 #define PI 3.14159265
     14 #define ls l,m,rt<<1
     15 #define rs m+1,r,rt<<1|1
     16 #define eps 1e-7
     17 #define pii pair<int,int>
     18 typedef unsigned long long ull;
     19 const int mod=1e3+5;
     20 const ll inf=0x3f3f3f3f3f3f3f;
     21 const int maxn=2e4+5;
     22 using namespace std;
     23 int n,m,head[maxn],to[maxn*2],w[maxn*2],nxt[maxn*2],cnt,siz[maxn],dep[maxn],rt,mx[maxn],s,q;
     24 int now[maxn],ans[120],que[120];
     25 bool vis[maxn];
     26 void add_edge(int x,int y,int l)
     27 {
     28     to[++cnt]=y;w[cnt]=l;nxt[cnt]=head[x];head[x]=cnt;
     29 }
     30 void dfs_rt(int v,int f)//找重心
     31 {
     32     siz[v]=1;mx[v]=0;
     33     for(int i=head[v];i;i=nxt[i])
     34     {
     35         if(to[i]==f||vis[to[i]])continue;
     36         dfs_rt(to[i],v);
     37         siz[v]+=siz[to[i]];
     38         mx[v]=max(siz[to[i]],mx[v]);
     39     }
     40     mx[v]=max(s-siz[v],mx[v]);
     41     if(rt==-1||mx[v]<mx[rt])rt=v;
     42 }
     43 void get_dep(int v,int f)
     44 {
     45     now[++now[0]]=dep[v];
     46     for(int i=head[v];i;i=nxt[i])
     47     {
     48         if(vis[to[i]]||to[i]==f)continue;
     49         dep[to[i]]=dep[v]+w[i];
     50         get_dep(to[i],v);
     51     }
     52 }
     53 int  get_sum(int v,int dis,int k)
     54 {
     55     int cn=0;now[0]=0;
     56     dep[v]=dis;get_dep(v,-1);
     57     sort(now+1,now+1+now[0]);
     58     for(int i=1;i<=now[0];i++)
     59     {
     60         if(now[i]*2>k)break;
     61         cn+=upper_bound(now+1,now+1+now[0],k-now[i])-lower_bound(now+1,now+1+now[0],k-now[i]);
     62     }
     63     return cn;
     64 }
     65 void get_ans(int v)
     66 {
     67     vis[v]=true;
     68     for(int i=1;i<=q;i++)ans[i]+=get_sum(v,0,que[i]);
     69     for(int i=head[v];i;i=nxt[i])
     70     {
     71         if(vis[to[i]])continue;
     72         for(int j=1;j<=q;j++)ans[j]-=get_sum(to[i],w[i],que[j]);
     73         rt=-1;s=siz[to[i]];dfs_rt(to[i],v);
     74         get_ans(rt);
     75     }
     76 }
     77 int main()
     78 {
     79         scanf("%d %d",&n,&q);
     80         for(int i=0;i<n-1;i++)
     81         {
     82             int u,v,l;
     83             scanf("%d %d %d",&u,&v,&l);
     84             add_edge(u,v,l);add_edge(v,u,l);
     85         }
     86         for(int i=1;i<=q;i++)
     87         {
     88             scanf("%d",&que[i]);
     89         }
     90         rt=-1;s=n;dfs_rt(1,-1);
     91         get_ans(rt);
     92         for(int i=1;i<=q;i++)
     93         {
     94             if(ans[i])
     95             {
     96                 printf("Yes
    ");
     97             }
     98             else printf("No
    ");
     99         }
    100     return 0;
    101 }
    View Code
  • 相关阅读:
    面试题47题
    深度学习面试
    神经网络训练中的梯度消失与梯度爆炸
    Softmax函数与交叉熵
    sourceTree 添加 ssh key 方法
    request.form()和request()的区别
    C#中Request.ServerVariables详细说明及代理
    Page_Load事件与IsPostBack属性
    CSS中position的absolute和relative用法
    读取游标
  • 原文地址:https://www.cnblogs.com/lhclqslove/p/9345665.html
Copyright © 2011-2022 走看看