BZOJ3697: 采药人的路径(点分治)
Description
采药人的药田是一个树状结构,每条路径上都种植着同种药材。
采药人以自己对药材独到的见解,对每种药材进行了分类。大致分为两类,一种是阴性的,一种是阳性的。
采药人每天都要进行采药活动。他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径。采药工作是很辛苦的,所以他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的。他想知道他一共可以选择多少种不同的路径。
Input
第1行包含一个整数N。
接下来N-1行,每行包含三个整数a_i、b_i和t_i,表示这条路上药材的类型。
Output
输出符合采药人要求的路径数目。
Sample Input
1 2 0
3 1 1
2 4 0
5 2 0
6 3 1
5 7 1
Sample Output
解题思路:
点分治要求在寻找到一条链时统计答案与重心在链的哪个位置无关。而显然这道题如果枚举重心为中转站是错误的,因为一条链只被统计一次,而中心位置很可能是错误的,所以我们需要修正这一点,就是统计重心路径上可能出现的中心位置。
换句话说,开四个桶来记录,分别记录当前子树内可能出现的中转站(出现过的距离重复,在差分的意义下说明出现和为0的区间),另外一个就是之前子树的答案,每次更新完合并桶就好了。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 typedef long long lnt; 5 const int N=100010; 6 struct pnt{ 7 int hd; 8 int dis; 9 int wgt; 10 bool vis; 11 }p[N]; 12 struct ent{ 13 int twd; 14 int lst; 15 int vls; 16 }e[N<<1]; 17 lnt f[N<<1][2],g[N<<1][2]; 18 int has[N<<1]; 19 int n; 20 lnt top; 21 int cnt; 22 lnt ans; 23 int lim; 24 int size; 25 int root; 26 int maxsize; 27 void ade(int f,int t,int v) 28 { 29 cnt++; 30 e[cnt].twd=t; 31 e[cnt].lst=p[f].hd; 32 e[cnt].vls=v; 33 p[f].hd=cnt; 34 return ; 35 } 36 void grc_dfs(int x,int f) 37 { 38 p[x].wgt=1; 39 int maxs=-1; 40 for(int i=p[x].hd;i;i=e[i].lst) 41 { 42 int to=e[i].twd; 43 if(to==f||p[to].vis) 44 continue; 45 grc_dfs(to,x); 46 p[x].wgt+=p[to].wgt; 47 if(p[to].wgt>maxs) 48 maxs=p[to].wgt; 49 } 50 if(maxs<size-p[x].wgt) 51 maxs=size-p[x].wgt; 52 if(maxs<maxsize) 53 { 54 maxsize=maxs; 55 root=x; 56 } 57 return ; 58 } 59 void ans_dfs(int x,int fa,int dep) 60 { 61 lim=std::max(lim,dep); 62 if(has[p[x].dis]) 63 f[p[x].dis][1]++; 64 else 65 f[p[x].dis][0]++; 66 has[p[x].dis]++; 67 for(int i=p[x].hd;i;i=e[i].lst) 68 { 69 int to=e[i].twd; 70 if(to==fa||p[to].vis) 71 continue; 72 p[to].dis=p[x].dis+e[i].vls; 73 ans_dfs(to,x,dep+1); 74 } 75 has[p[x].dis]--; 76 return ; 77 } 78 void bin_dfs(int x) 79 { 80 int maxd=0; 81 p[x].vis=true; 82 g[n][0]=1; 83 for(int i=p[x].hd;i;i=e[i].lst) 84 { 85 int to=e[i].twd; 86 if(p[to].vis) 87 continue; 88 p[to].dis=n+e[i].vls; 89 lim=1; 90 ans_dfs(to,to,1); 91 maxd=std::max(maxd,lim); 92 ans+=f[n][0]*(g[n][0]-1); 93 for(int j=-lim;j<=lim;j++) 94 ans+=g[n-j][1]*f[n+j][1]+g[n-j][1]*f[n+j][0]+g[n-j][0]*f[n+j][1]; 95 for(int j=n-lim;j<=n+lim;j++) 96 { 97 g[j][0]+=f[j][0]; 98 g[j][1]+=f[j][1]; 99 f[j][0]=f[j][1]=0; 100 } 101 } 102 for(int i=n-maxd;i<=n+maxd;i++) 103 g[i][0]=g[i][1]=0; 104 for(int i=p[x].hd;i;i=e[i].lst) 105 { 106 int to=e[i].twd; 107 if(p[to].vis) 108 continue; 109 root=0; 110 size=p[to].wgt; 111 maxsize=0x3f3f3f3f; 112 grc_dfs(to,to); 113 bin_dfs(root); 114 } 115 return ; 116 } 117 int main() 118 { 119 scanf("%d",&n); 120 for(int i=1;i<n;i++) 121 { 122 int a,b,c; 123 scanf("%d%d%d",&a,&b,&c); 124 c=c*2-1; 125 ade(a,b,c); 126 ade(b,a,c); 127 } 128 root=0; 129 size=n; 130 maxsize=0x3f3f3f3f; 131 grc_dfs(1,1); 132 bin_dfs(root); 133 printf("%lld\n",ans); 134 return 0; 135 }
转载于:https://www.cnblogs.com/blog-Dr-J/p/10159463.html
BZOJ3697: 采药人的路径(点分治)相关推荐
- bzoj千题计划248:bzoj3697: 采药人的路径
http://www.lydsy.com/JudgeOnline/problem.php?id=3697 点分治 路径0改为路径-1 g[i][0/1] 和 f[i][0/1]分别表示当前子树 和 已 ...
- bzoj3697 采药人的路径
Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药 ...
- BZOJ 3697: 采药人的路径 [点分治] [我想上化学课]
传送门 题意: 路径有$-1,1$两种权值,求有多少路径满足权值和为$0$且有一个点将路径分成权值和为$0$的两段 第四节课本来想去上化学,然后快上课了这道题还没调出来.....可恶我想上化学 昨天两 ...
- bzoj3784 树上的路径 点分治+RMQ+优先队列
题目分析 树上的路径路径?可以,这很点分治. 求最长的mmm条的长度?可以,着很优先队列. 但问题是,用优先队列只能做全局才能保证复杂度是对的,但点分治是分治就不能做全局. 于是对于每次点分治,都记录 ...
- 点分治问题 ----------- 2019西安邀请赛 j and and and[点分治]
题目链接 解题思路: 首先我们知道直接算很麻烦,我们对每条xor和为0的路径进行单独考虑. 1.我们知道对于每条xor和为0的路径,它对答案的贡献是,除了这个路径方向的子树大小的乘积. 2.那么很明显 ...
- 【技巧总结】——关于不知道放到哪里的小技巧
[技巧总结]--关于不知道放到哪里的小技巧 折半搜索 分治 0,1,-1转化 模型转换 [ExtendingSetofPointsExtending\;Set\;of\;PointsExtending ...
- 一句话题解(20180210~)
2.9 BZOJ 2006 [NOI2010]超级钢琴.这道题目几天之前就做了.做法是固定右端点,左端点在ST表上走,走法其实就是笛卡尔树的走法.完结撒花! BZOJ 1218 [HNOI2003]激 ...
- 动态规划:经典题目汇总
动态规划:经典题目汇总 文章目录 动态规划:经典题目汇总 一.动态规划的定义 二.经典例题 3.1 一维的DP:斐波那契数列.[使用最小花费爬楼梯](https://leetcode-cn.com/p ...
- YbtOJ#20078-[NOIP2020模拟赛B组Day7]路径之和【分治,Flody】
正题 题目链接:http://noip.ybtoj.com.cn/contest/108/problem/4 题目大意 nnn个点,每次只封闭一个点,求剩下点对两两之间的最短路和. 解题思路 Flod ...
最新文章
- 使用组策略实现文件复制
- C#如何在钉钉开发平台中创建部门
- LeetCode 100.相同的树(C++)
- matlab自动排版,工具方法| Matlab 简单绘图与排版
- 看了三张照片,这个AI只用20分钟破获六年“悬案”
- devops工程师_DevOps工程师的认证
- 【U-Net】【粗读】U-Net: Convolutional Networks for Biomedical Image Segmentation
- HTML示例06---水平线
- sun cluster 3.3 +oracle 10g R2 RAC with ASM on solaris 10 U9
- win10系统优化小工具:Windows10系统优化辅助工具.bat(批处理)
- GYM 101173 K.Key Knocking(构造)
- 微信小程序 之wx.previewImage图片预览(多张图片预览)
- 读书印记 - 《文案创作完全手册:文案大师教你一步步写出销售力》
- Qt绘制旋转的轮播图
- 经验谈系列 我们应该怎么给父母配电脑
- 基于矩阵分解的协同过滤算法
- [强制类型转换]C语言中的强制类型转换相关
- Steam Apex Legends 最简单领取方法,不需要改地区
- 知乎-产品经理观后总结
- linux画平面图软件,Sweet Home 3D傻瓜平面图软件,人人都能画出室内平面图