zoukankan      html  css  js  c++  java
  • HDU

    题目链接

    题意:统计树上每个结点中恰好出现了k次的颜色数。

    dsu on tree/线段树合并裸题。

    启发式合并1:(748ms)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 int n,m,k,a[N],b[N],nb,fa[N],son[N],siz[N],cnt[N],ans[N],now,ne,hd[N],ka;
     6 struct E {int v,nxt;} e[N<<1];
     7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     8 void dfs1(int u,int f) {
     9     fa[u]=f,son[u]=0,siz[u]=1;
    10     for(int i=hd[u]; ~i; i=e[i].nxt) {
    11         int v=e[i].v;
    12         if(v==fa[u])continue;
    13         dfs1(v,u),siz[u]+=siz[v];
    14         if(siz[v]>siz[son[u]])son[u]=v;
    15     }
    16 }
    17 void add(int x,int dx) {
    18     if(cnt[x]==k)--now;
    19     cnt[x]+=dx;
    20     if(cnt[x]==k)++now;
    21 }
    22 void cal(int u,int x) {
    23     add(a[u],x);
    24     for(int i=hd[u]; ~i; i=e[i].nxt) {
    25         int v=e[i].v;
    26         if(v!=fa[u])cal(v,x);
    27     }
    28 }
    29 void dfs2(int u,int f) {
    30     for(int i=hd[u]; ~i; i=e[i].nxt) {
    31         int v=e[i].v;
    32         if(v!=fa[u]&&v!=son[u])dfs2(v,0);
    33     }
    34     if(son[u])dfs2(son[u],1);
    35     add(a[u],1);
    36     for(int i=hd[u]; ~i; i=e[i].nxt) {
    37         int v=e[i].v;
    38         if(v!=fa[u]&&v!=son[u])cal(v,1);
    39     }
    40     ans[u]=now;
    41     if(!f) {
    42         add(a[u],-1);
    43         for(int i=hd[u]; ~i; i=e[i].nxt) {
    44             int v=e[i].v;
    45             if(v!=fa[u])cal(v,-1);
    46         }
    47     }
    48 }
    49 int main() {
    50     int T;
    51     for(scanf("%d",&T); T--;) {
    52         if(ka)puts("");
    53         printf("Case #%d:
    ",++ka);
    54         memset(hd,-1,sizeof hd),ne=0;
    55         memset(cnt,0,sizeof cnt);
    56         memset(ans,0,sizeof ans),now=0;
    57         scanf("%d%d",&n,&k);
    58         for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    59         for(int i=1; i<=n; ++i)b[i]=a[i];
    60         sort(b+1,b+1+n),nb=unique(b+1,b+1+n)-(b+1);
    61         for(int i=1; i<=n; ++i)a[i]=lower_bound(b+1,b+1+nb,a[i])-b;
    62         for(int i=1; i<n; ++i) {
    63             int u,v;
    64             scanf("%d%d",&u,&v);
    65             addedge(u,v),addedge(v,u);
    66         }
    67         dfs1(1,-1),dfs2(1,1);
    68         scanf("%d",&m);
    69         while(m--) {
    70             int u;
    71             scanf("%d",&u);
    72             printf("%d
    ",ans[u]);
    73         }
    74     }
    75     return 0;
    76 }
    View Code

    启发式合并2(加了dfs序的启发式合并,只比普通的快了一丁点):(702ms)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 int n,m,k,a[N],b[N],nb,fa[N],son[N],siz[N],cnt[N],ans[N],now,ne,hd[N],ka,tot,bg[N],ed[N],rnk[N];
     6 struct E {int v,nxt;} e[N<<1];
     7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     8 void dfs1(int u,int f) {
     9     fa[u]=f,son[u]=0,siz[u]=1,bg[u]=++tot,rnk[bg[u]]=u;
    10     for(int i=hd[u]; ~i; i=e[i].nxt) {
    11         int v=e[i].v;
    12         if(v==fa[u])continue;
    13         dfs1(v,u),siz[u]+=siz[v];
    14         if(siz[v]>siz[son[u]])son[u]=v;
    15     }
    16     ed[u]=tot;
    17 }
    18 void add(int x,int dx) {
    19     if(cnt[x]==k)--now;
    20     cnt[x]+=dx;
    21     if(cnt[x]==k)++now;
    22 }
    23 void dfs2(int u,int f) {
    24     for(int i=hd[u]; ~i; i=e[i].nxt) {
    25         int v=e[i].v;
    26         if(v!=fa[u]&&v!=son[u])dfs2(v,0);
    27     }
    28     if(son[u])dfs2(son[u],1);
    29     add(a[u],1);
    30     for(int i=hd[u]; ~i; i=e[i].nxt) {
    31         int v=e[i].v;
    32         if(v!=fa[u]&&v!=son[u])for(int i=bg[v]; i<=ed[v]; ++i)add(a[rnk[i]],1);
    33     }
    34     ans[u]=now;
    35     if(!f)for(int i=bg[u]; i<=ed[u]; ++i)add(a[rnk[i]],-1);
    36 }
    37 int main() {
    38     int T;
    39     for(scanf("%d",&T); T--;) {
    40         if(ka)puts("");
    41         printf("Case #%d:
    ",++ka);
    42         memset(hd,-1,sizeof hd),ne=0;
    43         memset(cnt,0,sizeof cnt),tot=0;
    44         memset(ans,0,sizeof ans),now=0;
    45         scanf("%d%d",&n,&k);
    46         for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    47         for(int i=1; i<=n; ++i)b[i]=a[i];
    48         sort(b+1,b+1+n),nb=unique(b+1,b+1+n)-(b+1);
    49         for(int i=1; i<=n; ++i)a[i]=lower_bound(b+1,b+1+nb,a[i])-b;
    50         for(int i=1; i<n; ++i) {
    51             int u,v;
    52             scanf("%d%d",&u,&v);
    53             addedge(u,v),addedge(v,u);
    54         }
    55         dfs1(1,-1),dfs2(1,1);
    56         scanf("%d",&m);
    57         while(m--) {
    58             int u;
    59             scanf("%d",&u);
    60             printf("%d
    ",ans[u]);
    61         }
    62     }
    63     return 0;
    64 }
    View Code

    启发式合并3(map版,原理与普通启发式合并相同,轻链合并到重链上,重链中的父结点的贡献直接加进子结点):(1185ms)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 int n,m,k,a[N],b[N],F[N],nb,ans[N],ne,hd[N],ka,fa[N],son[N],siz[N];
     6 map<int,int> mp[N];
     7 struct E {int v,nxt;} e[N<<1];
     8 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     9 void add(int u,int x,int dx) {
    10     if(mp[F[u]][x]==k)--ans[u];
    11     mp[F[u]][x]+=dx;
    12     if(mp[F[u]][x]==k)++ans[u];
    13 }
    14 void mg(int u,int v) {
    15     for(auto p:mp[F[v]])add(u,p.first,p.second);
    16     mp[F[v]].clear();
    17 }
    18 void dfs1(int u,int f) {
    19     fa[u]=f,son[u]=0,siz[u]=1;
    20     for(int i=hd[u]; ~i; i=e[i].nxt) {
    21         int v=e[i].v;
    22         if(v==fa[u])continue;
    23         dfs1(v,u),siz[u]+=siz[v];
    24         if(siz[v]>siz[son[u]])son[u]=v;
    25     }
    26 }
    27 void dfs2(int u) {
    28     F[u]=u;
    29     if(son[u])dfs2(son[u]),ans[u]=ans[son[u]],F[u]=F[son[u]];
    30     add(u,a[u],1);
    31     for(int i=hd[u]; ~i; i=e[i].nxt) {
    32         int v=e[i].v;
    33         if(v==fa[u]||v==son[u])continue;
    34         dfs2(v),mg(u,v);
    35     }
    36 }
    37 int main() {
    38     int T;
    39     for(scanf("%d",&T); T--;) {
    40         if(ka)puts("");
    41         printf("Case #%d:
    ",++ka);
    42         memset(hd,-1,sizeof hd),ne=0;
    43         memset(ans,0,sizeof ans);
    44         scanf("%d%d",&n,&k);
    45         for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    46         for(int i=1; i<=n; ++i)b[i]=a[i];
    47         sort(b+1,b+1+n),nb=unique(b+1,b+1+n)-(b+1);
    48         for(int i=1; i<=n; ++i)a[i]=lower_bound(b+1,b+1+nb,a[i])-b;
    49         for(int i=1; i<n; ++i) {
    50             int u,v;
    51             scanf("%d%d",&u,&v);
    52             addedge(u,v),addedge(v,u);
    53         }
    54         dfs1(1,-1),dfs2(1),mp[F[1]].clear();
    55         scanf("%d",&m);
    56         while(m--) {
    57             int u;
    58             scanf("%d",&u);
    59             printf("%d
    ",ans[u]);
    60         }
    61     }
    62     return 0;
    63 }
    View Code

    启发式合并4(map版,直接根据子树大小进行合并):(1263ms)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 int n,m,k,a[N],b[N],F[N],nb,ans[N],ne,hd[N],ka;
     6 map<int,int> mp[N];
     7 struct E {int v,nxt;} e[N<<1];
     8 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     9 void add(int u,int x,int dx) {
    10     if(mp[F[u]][x]==k)--ans[u];
    11     mp[F[u]][x]+=dx;
    12     if(mp[F[u]][x]==k)++ans[u];
    13 }
    14 void mg(int u,int v) {
    15     if(mp[F[u]].size()<mp[F[v]].size())ans[u]=ans[v],swap(F[u],F[v]);
    16     for(auto p:mp[F[v]])add(u,p.first,p.second);
    17     mp[F[v]].clear();
    18 }
    19 void dfs(int u,int fa) {
    20     add(F[u]=u,a[u],1);
    21     for(int i=hd[u]; ~i; i=e[i].nxt) {
    22         int v=e[i].v;
    23         if(v==fa)continue;
    24         dfs(v,u),mg(u,v);
    25     }
    26 }
    27 int main() {
    28     int T;
    29     for(scanf("%d",&T); T--;) {
    30         if(ka)puts("");
    31         printf("Case #%d:
    ",++ka);
    32         memset(hd,-1,sizeof hd),ne=0;
    33         memset(ans,0,sizeof ans);
    34         scanf("%d%d",&n,&k);
    35         for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    36         for(int i=1; i<=n; ++i)b[i]=a[i];
    37         sort(b+1,b+1+n),nb=unique(b+1,b+1+n)-(b+1);
    38         for(int i=1; i<=n; ++i)a[i]=lower_bound(b+1,b+1+nb,a[i])-b;
    39         for(int i=1; i<n; ++i) {
    40             int u,v;
    41             scanf("%d%d",&u,&v);
    42             addedge(u,v),addedge(v,u);
    43         }
    44         dfs(1,-1),mp[F[1]].clear();
    45         scanf("%d",&m);
    46         while(m--) {
    47             int u;
    48             scanf("%d",&u);
    49             printf("%d
    ",ans[u]);
    50         }
    51     }
    52     return 0;
    53 }
    View Code

    线段树合并:(1014ms)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 int n,m,k,a[N],b[N],nb,ans[N],ne,hd[N],ka,tot,rt[N],ls[N*20],rs[N*20],val[N*20],sum[N*20];
     6 #define mid ((l+r)>>1)
     7 struct E {int v,nxt;} e[N<<1];
     8 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     9 void pu(int u) {sum[u]=sum[ls[u]]+sum[rs[u]];}
    10 int newnode() {int u=++tot; ls[u]=rs[u]=val[u]=sum[u]=0; return u;}
    11 void add(int& u,int x,int dx,int l=1,int r=nb) {
    12     if(!u)u=newnode();
    13     if(l==r) {val[u]+=dx,sum[u]=val[u]==k; return;}
    14     x<=mid?add(ls[u],x,dx,l,mid):add(rs[u],x,dx,mid+1,r);
    15     pu(u);
    16 }
    17 void mg(int& u,int v,int l=1,int r=nb) {
    18     if(!u||!v) {u=u|v; return;}
    19     if(l==r) {val[u]+=val[v],sum[u]=val[u]==k; return;}
    20     mg(ls[u],ls[v],l,mid),mg(rs[u],rs[v],mid+1,r),pu(u);
    21 }
    22 void dfs(int u,int fa) {
    23     rt[u]=0,add(rt[u],a[u],1);
    24     for(int i=hd[u]; ~i; i=e[i].nxt) {
    25         int v=e[i].v;
    26         if(v==fa)continue;
    27         dfs(v,u),mg(rt[u],rt[v]);
    28     }
    29     ans[u]=sum[rt[u]];
    30 }
    31 int main() {
    32     int T;
    33     for(scanf("%d",&T); T--;) {
    34         if(ka)puts("");
    35         printf("Case #%d:
    ",++ka);
    36         memset(hd,-1,sizeof hd),ne=0;
    37         memset(ans,0,sizeof ans),tot=0;
    38         scanf("%d%d",&n,&k);
    39         for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    40         for(int i=1; i<=n; ++i)b[i]=a[i];
    41         sort(b+1,b+1+n),nb=unique(b+1,b+1+n)-(b+1);
    42         for(int i=1; i<=n; ++i)a[i]=lower_bound(b+1,b+1+nb,a[i])-b;
    43         for(int i=1; i<n; ++i) {
    44             int u,v;
    45             scanf("%d%d",&u,&v);
    46             addedge(u,v),addedge(v,u);
    47         }
    48         dfs(1,-1);
    49         scanf("%d",&m);
    50         while(m--) {
    51             int u;
    52             scanf("%d",&u);
    53             printf("%d
    ",ans[u]);
    54         }
    55     }
    56     return 0;
    57 }
    View Code

     还不够爽?再来个资瓷在线查询的可持久化线段树合并怎么样?就是有点吃内存。(1310ms)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 int n,m,k,a[N],b[N],nb,ne,hd[N],ka,tot,rt[N],ls[N*40],rs[N*40],val[N*40],sum[N*40];
     6 #define mid ((l+r)>>1)
     7 struct E {int v,nxt;} e[N<<1];
     8 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     9 void pu(int u) {sum[u]=sum[ls[u]]+sum[rs[u]];}
    10 int newnode() {int u=++tot; ls[u]=rs[u]=val[u]=sum[u]=0; return u;}
    11 void add(int& w,int u,int x,int dx,int l=1,int r=nb) {
    12     w=newnode();
    13     if(l==r) {val[w]=val[u]+dx,sum[w]=val[w]==k; return;}
    14     if(x<=mid)add(ls[w],ls[u],x,dx,l,mid),rs[w]=rs[u];
    15     else add(rs[w],rs[u],x,dx,mid+1,r),ls[w]=ls[u];
    16     pu(w);
    17 }
    18 void mg(int& w,int u,int v,int l=1,int r=nb) {
    19     if(!u||!v) {w=u|v; return;}
    20     w=newnode();
    21     if(l==r) {val[w]=val[u]+val[v],sum[w]=val[w]==k; return;}
    22     mg(ls[w],ls[u],ls[v],l,mid),mg(rs[w],rs[u],rs[v],mid+1,r),pu(w);
    23 }
    24 void dfs(int u,int fa) {
    25     rt[u]=0,add(rt[u],rt[u],a[u],1);
    26     for(int i=hd[u]; ~i; i=e[i].nxt) {
    27         int v=e[i].v;
    28         if(v==fa)continue;
    29         dfs(v,u),mg(rt[u],rt[u],rt[v]);
    30     }
    31 }
    32 int main() {
    33     int T;
    34     for(scanf("%d",&T); T--;) {
    35         if(ka)puts("");
    36         printf("Case #%d:
    ",++ka);
    37         memset(hd,-1,sizeof hd),ne=0;
    38         tot=0;
    39         scanf("%d%d",&n,&k);
    40         for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    41         for(int i=1; i<=n; ++i)b[i]=a[i];
    42         sort(b+1,b+1+n),nb=unique(b+1,b+1+n)-(b+1);
    43         for(int i=1; i<=n; ++i)a[i]=lower_bound(b+1,b+1+nb,a[i])-b;
    44         for(int i=1; i<n; ++i) {
    45             int u,v;
    46             scanf("%d%d",&u,&v);
    47             addedge(u,v),addedge(v,u);
    48         }
    49         dfs(1,-1);
    50         scanf("%d",&m);
    51         while(m--) {
    52             int u;
    53             scanf("%d",&u);
    54             printf("%d
    ",sum[rt[u]]);
    55         }
    56     }
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    java运算符优先级
    快排
    dpkg
    BZOJ 4487 染色问题
    BZOJ 3530 数数
    XSY 2754 求和
    BZOJ 4559 成绩比较
    广义容斥-二项式反演-容斥系数
    线性基学习笔记及其相关证明
    BZOJ 2754 喵星球上的点名
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10800982.html
Copyright © 2011-2022 走看看