[bzoj3697]采药人的路径_点分治
采药人的路径 bzoj-3697
题目大意:给你一个n个节点的树,每条边分为阴性和阳性,求满足条件的链的个数,使得这条链上阴性的边的条数等于阳性的边的条数,且这条链上存在一个节点,这个节点到一个端点的链也是阴阳相等,到另一个顶点也是阴阳相等。
注释:$1\le n \le 10^5$。
想法:点分治裸题,开始净想着怎么在一条阴阳相等的链上找点了。其实可以在找初步满足条件的链是就直接处理出完全满足条件者。首先,我们先令阳性为1,阴性为-1,求边权和为0即为阴阳相等。紧接着,我们定义
f[i][1]表示root的子树中满足到重心的链且边权和为i、存在一个点使得该点到这条链上到不是重心的另一个节点的边权和为0的条数。
f[i][0]同理,只是不存在这样的点。
g[i][1/0]表示边权和为-i。
特别地,因为所有的边权都是1 or -1,所以我可以在dfs链的时候直接判断出是否存在这样的节点。具体地:这条链的边权是x,如果这个节点相对于重心是根节点来讲存在一个祖先,使得这个祖先到根节点的边权和也是x,那么显然就存在这样的节点,就是那个祖先。然后,我们可以用l和r分别表示这个点之前祖先的边权和所能达到的下界和上界。因为边权是1 or -1,所以$[l,r]$之间的所有值都是可以取到的。这就处理出了f和g数组。
剩下的,就是运用单步容斥和简单的点分治模板套用,注意size的问题(抄的GXZlegend的代码,所以就没特意更改size的错误)。
最后,附上丑陋的代码... ...
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
}#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
int head[N],to[N<<1],val[N<<1],next[N<<1],cnt,vis[N],si[N],ms[N],sum,root,md;
long long f[N][2],g[N][2],ans;
inline void add(int x,int y,int z)
{
to[++cnt]=y,val[cnt]=z,next[cnt]=head[x],head[x]=cnt;
}
void getroot(int x,int fa)
{
si[x]=1,ms[x]=0;
for(int i=head[x];i;i=next[i])
if(!vis[to[i]]&&to[i]!=fa)
getroot(to[i],x),si[x]+=si[to[i]],ms[x]=max(ms[x],si[to[i]]);
ms[x]=max(ms[x],sum-si[x]);
if(ms[x]<ms[root]) root=x;
}
void calc(int x,int fa,int now,int cnt)
{
if(now==0)
{
if(cnt>=2)ans++;
cnt++;
}
for(int i=head[x];i;i=next[i])
if(!vis[to[i]]&&to[i]!=fa)
calc(to[i],x,now+2*val[i]-1,cnt);
}
void dfs(int x,int fa,int now,int l,int r)
{
if(now>=l&&now<=r)
{
if(now>=0)f[now][1]++;
else g[-now][1]++;
}
else
{
if(now>=0)f[now][0]++;
else g[-now][0]++;
}
l=min(l,now),r=max(r,now),md=max(md,max(-l,r));
for(int i=head[x];i;i=next[i])
if(!vis[to[i]]&&to[i]!=fa)
dfs(to[i],x,now+val[i]*2-1,l,r);
}
void solve(int x)
{
vis[x]=1,md=0,calc(x,0,0,0);
dfs(x,0,0,1,-1),ans+=f[0][1]*(f[0][1]-1)/2,f[0][0]=f[0][1]=0;
for(int i=1;i<=md;i++)ans+=f[i][0]*g[i][1]+f[i][1]*g[i][0]+f[i][1]*g[i][1],f[i][0]=f[i][1]=g[i][0]=g[i][1]=0;
for(int i=head[x];i;i=next[i])
{
if(!vis[to[i]])
{
md=0,dfs(to[i],0,2*val[i]-1,0,0),ans-=f[0][1]*(f[0][1]-1)/2,f[0][0]=f[0][1]=0;
for(int j=0;j<=md;j++)ans-=f[j][0]*g[j][1]+f[j][1]*g[j][0]+f[j][1]*g[j][1],f[j][0]=f[j][1]=g[j][0]=g[j][1]=0;
sum=si[to[i]],root=0,getroot(to[i],0),solve(root);
}
}
}
int main()
{
int n,x,y,z;
scanf("%d",&n);
for(int i=1;i<n;i++)scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
sum=n;
root=0;
ms[0]=n;
getroot(1,0);
solve(root);
printf("%lld\n",ans);
return 0;
}
小结:在更新l和r时now的值并没有进行更改,所以不需要特殊处理,也就是当前的calc的now是可以直接拿来用的。
[bzoj3697]采药人的路径_点分治的更多相关文章
- BZOJ_3697_采药人的路径_点分治
BZOJ_3697_采药人的路径_点分治 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性 ...
- BZOJ3697 采药人的路径 【点分治】
题目 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药活动.他选择的路径 ...
- BZOJ3697: 采药人的路径(点分治)
Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动 ...
- 2019.01.09 bzoj3697: 采药人的路径(点分治)
传送门 点分治好题. 题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数. 思路: 考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数 ...
- 【BZOJ-3697&3127】采药人的路径&YinandYang 点分治 + 乱搞
3697: 采药人的路径 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 681 Solved: 246[Submit][Status][Discus ...
- bzoj千题计划248:bzoj3697: 采药人的路径
http://www.lydsy.com/JudgeOnline/problem.php?id=3697 点分治 路径0改为路径-1 g[i][0/1] 和 f[i][0/1]分别表示当前子树 和 已 ...
- 【BZOJ3697】采药人的路径(点分治)
题意:采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径是很 ...
- BZOJ3697采药人的路径——点分治
题目描述 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径 ...
- BZOJ3697:采药人的路径(点分治)
Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药 ...
随机推荐
- 如何为你的Go应用创建轻量级Docker镜像?
介绍 多什么? 简单来讲,多阶段. 多阶段允许在创建Dockerfile时使用多个from,它非常有用,因为它使我们能够使用所有必需的工具构建应用程序.举个例子,首先我们使用Golang的基础镜像,然 ...
- Sublime Text 汉化插件
https://blog.csdn.net/heyangyi_19940703/article/details/51869502 一.Sublime Text工具介绍: Sublime Text 是一 ...
- [NOI1997] 积木游戏(dp)
COGS 261. [NOI1997] 积木游戏 http://www.cogs.pro/cogs/problem/problem.php?pid=261 ★★ 输入文件:buildinggame ...
- 苹果树(线段树+Dfs序)
1228 苹果树 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总 ...
- ACM_黯然销魂?
黯然销魂? Time Limit: 2000/1000ms (Java/Others) Problem Description: 发神集训表现出色,决定要送他鸡翅,但是锴神决定不让他那么容易拿到,所以 ...
- Spring思维课程导图——bean属性的设置
- Java中 == 和 equals()
记住三句话 1. 语义上:==指的是内存引用一样.equals是指的是逻辑相等.逻辑相等具体的意思由编写者决定(即在引用类型中,"=="是比较两个引用是否指向堆内存里的同一个地址( ...
- jsp%不能解析
做一个传值问题时 遇到错误 百度了一下是百分号不能解析,实在搞不明白为什么,以前这样做好好的,这次就不行了,不知道为什么,后来偶然一次把标签删了 错误居然没了,难道struts2的这个标签不支持这样传 ...
- csf 课件转化为wmv正常格式
1. 下载csf文件到本地:如下图 2.从下面百度网盘下载到本地: https://pan.baidu.com/s/1BBbgq n85a 3.安装并出现下面图标,点击打开 4. 运行如下图 5. ...
- Tomcat服务器安装与第一个jsp网页程序
1.安装tomcat服务器之前需要,先安装相应版本的jdk,个人理解Tomcat的大部分功能是使用了java的 jdk jar包的. jdk包下载方式网上可以查到 下载完后可以解压到一个指定目录,并在 ...