hdu 4670 Cube number on a tree,平衡树,启发式合并
来源:互联网 发布:网络神曲panama 编辑:程序博客网 时间:2024/06/08 01:12
又找到一个启发式合并的练手题。
还不太清楚这种算法的可以先看看这篇。
这题问的是有多少个路径满足路径的乘积是立方数。
其实分解质因数后,用一个long long保存状态,这样就变成了多少条路径满足路径的状态和等于0。
在树的每个节点建一个平衡树,自下而上合并时统计,很容易得到这个结果。
貌似在相同复杂度的情况下,启发式合并的效果都要比点分治的效果要好(常数要小)。
1000ms,排名还是挺靠前的。
还不太清楚这种算法的可以先看看这篇。
这题问的是有多少个路径满足路径的乘积是立方数。
其实分解质因数后,用一个long long保存状态,这样就变成了多少条路径满足路径的状态和等于0。
在树的每个节点建一个平衡树,自下而上合并时统计,很容易得到这个结果。
貌似在相同复杂度的情况下,启发式合并的效果都要比点分治的效果要好(常数要小)。
1000ms,排名还是挺靠前的。
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<cstdio>#include<cstring>#include<map>using namespace std;#define NN 51000int te;int fi[NN];struct edge{int v,ne;}ed[NN*2];map<long long,int> mp[NN];int tr;int root[NN];int cnt[NN];int son[NN];long long sum[NN];long long pp[50];long long state[NN];long long ans;int n,k;void addedge(int fr,int to){ ++te;ed[te].ne=fi[fr];fi[fr]=te;ed[te].v=to;}void getpr(int now,long long v){ int i,tmp; long long sta=0; for(i=1;i<=k;++i){ tmp=0; while(1){ if (v%pp[i]) break; v=v/pp[i]; tmp++; } tmp=tmp%3; sta=sta*3+tmp; } state[now]=sta;}int tsv[50];long long mergeval(long long v1,long long v2){ long long ret=0; int i; for(i=k;i>=1;--i){ tsv[i]=(v1+v2)%3; v1/=3;v2/=3; } for(i=1;i<=k;++i){ ret=ret*3+tsv[i]; } return ret;}long long rev(long long v1,long long v2){ long long ret=0; int i; for(i=k;i>=1;--i){ tsv[i]=((v1-v2)%3+3)%3; v1/=3;v2/=3; } for(i=1;i<=k;++i){ ret=ret*3+tsv[i]; } return ret;}void dfs(int u,int fa){ int ts=1; int e,v; long long tmp; int mas=-1;son[u]=u; int nr,vr; map<long long,int>::iterator it; for(e=fi[u];e!=-1;e=ed[e].ne){ v=ed[e].v; if (v==fa) continue; dfs(v,u); ts+=cnt[v]; if (cnt[v]>mas) {mas=cnt[v];son[u]=v;} } cnt[u]=ts; if (ts==1){ if (state[u]==0) ans++; root[u]=++tr; mp[root[u]][0]=1; sum[u]=state[u]; } else{ tmp=state[u]; if (state[u]==0) ans++; sum[u]=mergeval(tmp,sum[son[u]]); nr=root[u]=root[son[u]]; ans+=mp[nr][rev(0,sum[u])]; mp[nr][rev(0,sum[son[u]])]++; for(e=fi[u];e!=-1;e=ed[e].ne){ v=ed[e].v; if (v==fa||v==son[u]) continue; vr=root[v]; for(it=mp[vr].begin();it!=mp[vr].end();++it){ tmp=mergeval(sum[u],sum[v]); tmp=mergeval(tmp,it->first); tmp=rev(0,tmp); ans+=(long long)it->second*mp[nr][tmp]; } for(it=mp[vr].begin();it!=mp[vr].end();++it){ tmp=mergeval(sum[v],it->first); tmp=rev(tmp,sum[son[u]]); mp[nr][tmp]+=it->second; } } }}int main(){ //freopen("4670in.txt","r",stdin); int i; int a,b; long long la; while(scanf("%d",&n)!=EOF){ scanf("%d",&k); for(i=1;i<=k;++i){ scanf("%I64d",&pp[i]); } for(i=1;i<=n;++i){ scanf("%I64d",&la); getpr(i,la); mp[i].clear(); } memset(fi,-1,sizeof(fi)); te=-1; for(i=1;i<n;++i){ scanf("%d%d",&a,&b); addedge(a,b); addedge(b,a); } ans=0; tr=0; dfs(1,-1); printf("%I64d\n",ans); } return 0;}
0 0
- hdu 4670 Cube number on a tree,平衡树,启发式合并
- HDU 4670 Cube number on a tree
- hdu 4670 Cube number on a tree
- HDU 4670 Cube number on a tree
- 【树的分治】 HDU 4670 Cube number on a tree
- [hdu 6191 Query on A Tree] 字典树启发式合并
- hdu 4670 Cube number on a tree(点分治)
- 【HDU】4670 Cube number on a tree 点分治
- HDOJ 4670: Cube number on a tree
- HDU 4670 Cube number on a tree ( 树的点分治 )
- HDU 6191 && 2017广西邀请赛:Query on A Tree(字典树启发式合并)
- 2017 广西邀请赛&& hdu 6191 Query on A Tree(字典树启发式合并)
- HDU6191Query on A Tree(字典树启发式合并)
- hdu4812 D Tree,平衡树,启发式合并
- poj1741 Tree,平衡树,启发式合并
- 【平衡树启发式合并】POJ1741[Tree]题解
- HDU4670 Cube number on a tree
- HDU4670-Cube number on a tree
- android中LocalBroadcastManager的使用
- 参考练习,代码基本已经理解 最后取模部分有待理解。
- 大数据-2.5亿个数据-统计不重复
- [LeetCode] Longest Palindromic Substring
- taskset榨干服务器CPU:让进程运行在指定的CPU内核
- hdu 4670 Cube number on a tree,平衡树,启发式合并
- 字符串分组
- WaitForSingleObject
- 计算32位整形数内含有1的个数
- C语言编程
- 转]史上最快消息内核——ZeroMQ
- C语言编译、链接
- ios tableView (tableView添加标题,头尾和改变cell的宽度)
- GCC的内嵌汇编语法