2019.01.09 bzoj3697: 采药人的路径(点分治)
传送门
点分治好题。
题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数。
思路:
考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数。
然后发现对于一个点ppp,经过它的这样的路径满足如下至少一个条件:
- ∃v\exist v∃v满足dist(v,p)=0&&∃v0∈roadv,pdist(v,p)=0\&\&\exist v_0\in road_{v,p}dist(v,p)=0&&∃v0∈roadv,p满足dist(v0,v)=0dist(v_0,v)=0dist(v0,v)=0
- ∃v1,v2\exist v_1,v_2∃v1,v2满足$dist(v_1,p)=0,dist(v_2,p)=0
- ∃v1,v2\exist v_1,v_2∃v1,v2满足dist(v1,p)+dist(v2,p)=0&&∃v0∈roadv1,pdist(v_1,p)+dist(v_2,p)=0\&\&\exist v_0\in road_{v_1,p}dist(v1,p)+dist(v2,p)=0&&∃v0∈roadv1,p满足distv0,p=distv1,pdist{v_0,p}=dist_{v_1,p}distv0,p=distv1,p
- ∃v1,v2\exist v_1,v_2∃v1,v2满足dist(v1,p)+dist(v2,p)=0&&∃v0∈roadv2,pdist(v_1,p)+dist(v_2,p)=0\&\&\exist v_0\in road_{v_2,p}dist(v1,p)+dist(v2,p)=0&&∃v0∈roadv2,p满足distv0,p=distv2,pdist{v_0,p}=dist_{v_2,p}distv0,p=distv2,p
然后点分容斥处理即可,注意不要忘记第一种情况的讨论。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define ri register int
using namespace std;
const int N=1e5+5;
int n,siz[N],msiz[N],rt=0,all=0,lim;
bool vis[N];
typedef pair<int,int> pii;
typedef long long ll;
vector<pii>e[N];
ll ans=0,cnt[2][N][2]={0};
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
void findroot(int p,int fa){
siz[p]=1,msiz[p]=0;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i].fi)==fa||vis[v])continue;
findroot(v,p),siz[p]+=siz[v],msiz[p]=max(msiz[p],siz[v]);
}
msiz[p]=max(msiz[p],all-siz[p]);
if(msiz[p]<msiz[rt])rt=p;
}
void getdis(int p,int fa,int dist,int down,int up){
if(dist>=down&&dist<=up){
if(dist>=0)++cnt[0][dist][1];
if(dist<0)++cnt[1][-dist][1];
}
else{
if(dist>=0)++cnt[0][dist][0];
if(dist<0)++cnt[1][-dist][0];
}
down=min(down,dist),up=max(up,dist),lim=max(lim,max(-down,up));
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i].fi)==fa||vis[v])continue;
getdis(v,p,dist+e[p][i].se,down,up);
}
}
inline void calc(int p,int pre,int tmp){
ll sum=0;
lim=0;
if(tmp==1)getdis(p,0,pre,1,-1);
else getdis(p,0,pre,0,0);
sum+=cnt[0][0][1]*(cnt[0][0][1]-1)/2,cnt[0][0][0]=cnt[0][0][1]=0;
for(ri i=1;i<=lim;++i){
sum+=cnt[0][i][0]*cnt[1][i][1];
sum+=cnt[0][i][1]*cnt[1][i][0];
sum+=cnt[0][i][1]*cnt[1][i][1];
cnt[0][i][0]=cnt[0][i][1]=cnt[1][i][0]=cnt[1][i][1]=0;
}
ans+=sum*tmp;
}
void solve(int p,int fa,int tim,int dist){
if(!dist){
if(tim>=2)++ans;
++tim;
}
for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i].fi)!=fa&&!vis[v])solve(v,p,tim,dist+e[p][i].se);
}
void dfs(int p){
vis[p]=1,solve(p,0,0,0),calc(p,0,1);
for(ri i=0,v;i<e[p].size();++i){
if(vis[v=e[p][i].fi])continue;
calc(v,e[p][i].se,-1),rt=0,all=siz[v],findroot(v,0),dfs(rt);
}
}
int main(){
freopen("lx.in","r",stdin);
n=read();
for(ri i=1,u,v,w;i<n;++i)u=read(),v=read(),w=read()?1:-1,e[u].push_back(pii(v,w)),e[v].push_back(pii(u,w));
rt=0,all=n,msiz[rt]=n,findroot(1,0),dfs(rt);
cout<<ans;
return 0;
}
2019.01.09 bzoj3697: 采药人的路径(点分治)的更多相关文章
- BZOJ3697采药人的路径——点分治
题目描述 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径 ...
- BZOJ3697:采药人的路径(点分治)
Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药 ...
- [bzoj3697]采药人的路径——点分治
Brief Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天 ...
- 2019.01.09 bzoj2599: [IOI2011]Race(点分治)
传送门 题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. 思路: 考虑点分治如何合并. 我们利用树形dpdpdp求树的直径的方法,边dfsdfsdfs子树边统计答案即可. 代码: ...
- AWS re:Invent(2019.01.09)
时间:2019.01.09地点:北京国际饭店
- 【BZOJ3697】采药人的路径 点分治
[BZOJ3697]采药人的路径 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是 ...
- [bzoj3697]采药人的路径_点分治
采药人的路径 bzoj-3697 题目大意:给你一个n个节点的树,每条边分为阴性和阳性,求满足条件的链的个数,使得这条链上阴性的边的条数等于阳性的边的条数,且这条链上存在一个节点,这个节点到一个端点的 ...
- bzoj千题计划248:bzoj3697: 采药人的路径
http://www.lydsy.com/JudgeOnline/problem.php?id=3697 点分治 路径0改为路径-1 g[i][0/1] 和 f[i][0/1]分别表示当前子树 和 已 ...
- #学习笔记# VALSE 2019.01.09 朱俊彦 --- Learning to Synthesize Images, Videos, and 3D Objects
视频类型:VALSE-webinar 报告时间:2019年01月09日 报告人:MIT朱俊彦 报告题目:Learning to Synthesize Images, Videos, and 3D Ob ...
随机推荐
- Dbutils 的JDBC链接
最近实践周,再次用到了这个Apache的开源工具包就在次对着个方面进行了复习 1.JDBC的基本 操作姿势 2.JDBC的步骤是 1.添加驱动包 Class.forName("oracle. ...
- POJ-1458.CommonSubsequence.(DP:最长公共子序列裸题)
本题大意:给出两个字符串,让你求出最长公共子序列的长度并输出. 本题思路:本题是经典的DP问题,由于是两个字符串,那么我们就用一个二维数组来进行区分,用dp[ i ][ j ]来表示在s1和s2中分别 ...
- Python+Selenium学习--启动及关闭浏览器
场景 页面上弹出的对话框是自动化测试经常会遇到的一个问题:很多情况下对话框是一个iframe,如之前iframe介绍的例子,处理起来稍微有点麻烦:但现在很多前端框架的对话框是div 形式的,这就让我们 ...
- 【Linux 线程】常用线程函数复习《四》
1.线程属性的设置 /************************************************************************* > File Name: ...
- sql2000三个表的级联删除
sql2000中三个表级联删除 create table a( id int primary key, Content varchar(50)) create table b( id ...
- javascript 获取html元素的三种方法
操作HTML元素 你首先找到该元素. 三种方法来做这件事: 通过id找到HTML元素 通过标签名找到HTML元素 通过类名找到HTML元素 通过id查找HTML元素 在DOM中查找HTML元素的最简单 ...
- python 数据类型 总结
按存储空间的占用分(从低到高) 数字 字符串 集合:无序,即无序存索引相关信息 元组:有序,需要存索引相关信息,不可变 列表:有序,需要存索引相关信息,可变,需要处理数据的增删改 字典:无序,需要存k ...
- maven项目打包发布到私有仓库
在项目开发中通常会引用其他的jar,怎样把自己的项目做为一个jar包的形式发布到私服仓库中,主要有以下三个步骤 (怎样配置maven私服仓库,就不再这里说明了,可以参考以前的文章)1.在maven的s ...
- C# json解析字符串总是多出双引号
json好久没用了,今天在用到json的时候,发现对字符串做解析的时候总是多出双引号. 代码如下: string jsonText = "{'name':'test','phone':'18 ...
- memcached 一致性hash原理
memcache 是一个分布式的缓存系统,但是本身没有提供集群功能,在大型应用的情况下容易成为瓶颈.但是客户端这个时候可以自由扩展,分两阶段实现.第一阶段:key 要先根据一定的算法映射到一台memc ...