HDU4670 Cube number on a tree
来源:互联网 发布:linux 禁用端口 编辑:程序博客网 时间:2024/06/06 02:18
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4670
算法:基于点的树链分治
思路:
//树基于点的分治算法,可以参见国家集训队论文:2009年漆子超《分治算法在树的路径问题中的应用》
/*
000111222
+ 012012012
----------------------
= 012120201
*/
//Mul[u,v] 等于点u到点v的乘积中,各个素数的个数对3取余后的一个数列
//对于每一个Mul[u, S], 求Mul(S, v]+Mul[u,S]=0的个数(S为分治点)
//用map记录下所有Mul[S,u]的状态(用longlong保存3进制数),再用一个map保存取出分治点S以后(S,v]的状态,对于第一个map中的每一个状态,求在第二个map中是否存在它的互补状态
注意:
//第一次遇到手动扩栈的题,检查了好长时间
//素数有可能超过int
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<cstdio>#include<cstring>#include<map>using namespace std;#define LL __int64const int M = 50010;LL pri[35];//保存素数int Num;//素数的个数int num[M][30];//每个数的化简struct Edge { int v, next;} edge[M << 1];int head[M], E;//邻接表参数LL ans = 0;//保存最终结果int mmax, root, size[M], mx[M], vis[M];//求重点的参数int tmp_cnt;//计算类似8,27,125这样单独成区间的区间个数int dis[M][30];//保存区间[S,i]中第j个素数的个数dis[i][j]map<LL, LL> er, mp;//er是计算3进制下需要匹配的数的个数,mp是计算分治点S到目标点Q,Mul[S,Q]在3进制下得到的数map<LL, LL>::iterator it;void init() { ans = E = 0; memset(vis, 0, sizeof(vis)); memset(head, -1, sizeof(head)); memset(num, 0, sizeof(num));}void add_edge(int s, int v) { edge[E].v = v; edge[E].next = head[s]; head[s] = E++;}void dfs_uu(int u, int fa) { size[u] = 1; mx[u] = 0; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if (v == fa || vis[v])continue; dfs_uu(v, u); size[u] += size[v]; if (size[v] > mx[u]) mx[u] = size[v]; }}void dfs_u(int u, int fa, int r) { if (size[r] - size[u] > mx[u]) mx[u] = size[r] - size[u]; if (mmax > mx[u]) { mmax = mx[u]; root = u;} for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if (v == fa || vis[v]) continue; dfs_u(v, u, r); }}//以上两个函数求重点void dfs_dis(int u, int fa, int r) { LL tmp = 0, sum = 0, sum_nee = 0; for (int i = 0; i < Num; i++) { dis[u][i] = dis[fa][i] + num[u][i]; if (dis[u][i] > 2) dis[u][i] -= 3; tmp = 3 - dis[u][i] + dis[r][i]; if (tmp >= 3) tmp -= 3; sum = sum * 3 + tmp; sum_nee = sum_nee * 3 + dis[u][i]; } if (sum == sum_nee) tmp_cnt++; er[sum]++; mp[sum_nee]++; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if (v == fa || vis[v]) continue; dfs_dis(v, u, r); }}LL cala(int u, int fa) { mp.clear(); er.clear(); LL tt = 0; tmp_cnt = 0; if (fa != 0) for (int i = 0; i < Num; i++) dis[fa][i] = num[fa][i]; dfs_dis(u, fa, fa == 0 ? u : fa); for (it = er.begin(); it != er.end(); it++) { if (mp.find(it->first) != mp.end()) tt += it->second * mp[it->first]; } return (tt - tmp_cnt) / 2 + tmp_cnt;}//以上两个【核心】函数求分治区间中满足条件的点对~void solve(int u) { int rt = 0; mmax = 123456; root = u; dfs_uu(u, -1); dfs_u(u, -1, u); ans += cala(root, 0); vis[root] = 1; rt = root; for (int i = head[rt]; i != -1; i = edge[i].next) { int v = edge[i].v; if (vis[v]) continue; ans -= cala(v, rt); solve(v); }}int main() { int n; while (scanf("%d", &n) != EOF) { int i, j; LL val; init(); scanf("%d", &Num); for (i = 0; i < Num; i++) { scanf("%I64d", &pri[i]); } for (i = 1; i <= n; i++) { scanf("%I64d", &val); for (j = 0; j < Num; j++) { while (val % pri[j] == 0) { num[i][j]++; val = val / pri[j]; if (num[i][j] > 2) num[i][j] -= 3; } } } int a, b; for (i = 0; i < n - 1; i++) { scanf("%d%d", &a, &b); add_edge(a, b); add_edge(b, a); } solve(1); printf("%I64d\n", ans); } return 0;}
- HDU4670 Cube number on a tree
- HDU4670-Cube number on a tree
- hdu4670 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 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 4670 Cube number on a tree,平衡树,启发式合并
- 2013 多校第七场 hdu 4670 Cube number on a tree(树上点的分治)
- HackerRank - number-game-on-a-tree
- hdu4670
- Draw a cube on Excel Worksheet
- spoj375Query on a tree
- Query on A Tree
- 【树形DP】 HDU 4276 The Ghost Blows Light
- test
- const_cast
- HDU——4666 Hyperspace
- 关于Hibernate的oracle主键id生成策略uuid、native和sequence
- HDU4670 Cube number on a tree
- Unity3D基础知识梳理
- 插件的概念及原理
- Eclipse IDE for c++配置
- HDU1869:六度分离
- 软件插件技术的原理与实现
- GetMemory函数的几种经典考法
- poj 1830 开关问题 高斯消元
- NS2中的多速率MAC
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
特房莱昂公馆
特房樾琴湾
特房银溪墅府
特房银溪墅府二手房
特技人
特技摩托
特技
bb特技表演
特技滑板
神武特技
特技摩托车2
的特技
三国志11特技
血色衣冠特技全解析
特技防火卷帘门
楚留香特技怎么升级
破碎无双特技
楚留香特技怎么弄
三国志8学特技
慈航普度特技
楚留香打造特技技巧
三国志11威力加强版特技
提亚马特
特提
fgo提亚马特
雅特兰提斯
提亚马特600w怎么打
特提是什么意思
特摄联盟
特摄1959
日本特摄
特摄片
特摄ol无限
超级特摄时代
特摄之神
中国特摄联盟
特摄剧
日本三大特摄有哪些
日本所有特摄
日本三大特摄
特摄ol无限强化免费看