小道士的矫情之路;
点分治,
对于每个子树,处理其内经过根(重心)的路径,然后递归下一层子树;
如何处理经过根的合法路径
合法有两个要求;
把输入的0改成-1后
1.len=0;
2.存在一个点i使被她分开的两个路径len均为零;
在每次统计中我们可以dfs统计每条从根开始的路径(half_way),
任意两条这样的路径拼成一条可能合法的路径;
check合法?
通过dfs;
统计1,每个half_way的len
还要统计,2,这个half_way上是否有一个点到half_way的终点(根之外的那个)的len=0;
一,两个half_way的len加为0才可能合法;
二,两个half_way中至少一个满足“有一个点到half_way的终点(根之外的那个)的len=0”;
只要满足一&&二,则路径合法;(自己思考why?)
1很好统计;
关键是2;
可以考虑维护一个桶;
如果root到i的路径len=x,且桶x已经有值了,则i的二合法;(自己思考why?)
由于这里细节极多,不好全部言明,故直接看代码:
 long long  get_ans(int root,int w){
int i,j,k,l,kk,ll;
long long ans=;
tot=;if(w)map[zero]=;
dfs_ans(root,w,);j=tot;
sort(hw+,hw+tot+,cmp);
for(i=;i<j;i++){
while(hw[i].d+hw[j].d>&&i<j)
j--;
if(hw[i].d+hw[j].d==){
k=l=;kk=i;ll=j;
if(hw[i].d==){
for(;i<=j;i++){
if(hw[i].can>=)k++;
if(hw[i].can==)l++;
}
ans+=(long long)(k+l)*(k+l-)/;
ans+=(long long)k*(ll-kk+-l-k);
break;
}
while(){
if(hw[i].can)k++;i++;
if(hw[i].d!=hw[i-].d)break;
}
while(){
if(hw[j].can)l++;j--;
if(hw[j].d!=hw[j+].d)break;
}
ans+=(long long)k*(ll-j-l)+l*(i-kk-k)+k*l;i--;
}
}
if(w)map[zero]=;
return ans;
}
void dfs_ans(int now,int sum,int fa){
hw[++tot].d=sum;
hw[tot].can=map[zero+sum];
map[zero+sum]++;
for(int i=first[now];i;i=e[i].next)
if(e[i].to!=fa&&!vis[e[i].to])
dfs_ans(e[i].to,sum+e[i].d,now);
map[zero+sum]--;
}

由于这个操作是单次O(logn)的,于是我的做法比标解多了一个不大log;

(标解O(nlogn),本人O(nlog²n),......大约是这样)

之前桶没清干净,拍了好久没发现;

总代码:

 #include<cstdio>
#include<algorithm>
using namespace std;
const int zero=;
int n,tot;
long long ans;
struct half_way{
int d,can;
}hw[];
int map[],vis[],size[],lsize[];
struct ss{
int to,next,d;
}e[];
int first[],num;
bool cmp(half_way a,half_way b){
return a.d<b.d;
}
void build(int ,int ,int );
void part_dfs(int );
void dfs_size(int ,int );
int dfs_root(int ,int ,int );
long long get_ans(int ,int );
void dfs_ans(int ,int ,int );
int main()
{
int i,j,k,l;
scanf("%d",&n);
for(i=;i<n;i++){
scanf("%d%d%d",&j,&k,&l);
l=l?:-;
build(j,k,l);
build(k,j,l);
}
part_dfs();
printf("%lld",ans);
return ;
}
void build(int f,int t,int wi){
e[++num].next=first[f];
e[num].to=t;e[num].d=wi;
first[f]=num;
}
void part_dfs(int now){
int i,root;
dfs_size(now,);
root=dfs_root(now,,now);
ans+=get_ans(root,);
vis[root]=;
for(i=first[root];i;i=e[i].next)
if(!vis[e[i].to]){
ans-=get_ans(e[i].to,e[i].d);
part_dfs(e[i].to);
}
}
void dfs_size(int now,int fa){
size[now]=;
for(int i=first[now];i;i=e[i].next)
if(!vis[e[i].to]&&e[i].to!=fa){
dfs_size(e[i].to,now);
size[now]+=size[e[i].to];
}
}
int dfs_root(int now,int fa,int r){
int i,root=-,wroot;
lsize[now]=size[r]-size[now];
for(i=first[now];i;i=e[i].next)
if(!vis[e[i].to]&&e[i].to!=fa){
if(size[e[i].to]>lsize[now])
lsize[now]=size[e[i].to];
wroot=dfs_root(e[i].to,now,r);
if(lsize[wroot]<lsize[root]||root==-)
root=wroot;
}
if(lsize[now]<lsize[root]||root==-)
root=now;
return root;
}
long long get_ans(int root,int w){
int i,j,k,l,kk,ll;
long long ans=;
tot=;if(w)map[zero]=;
dfs_ans(root,w,);j=tot;
sort(hw+,hw+tot+,cmp);
for(i=;i<j;i++){
while(hw[i].d+hw[j].d>&&i<j)
j--;
if(hw[i].d+hw[j].d==){
k=l=;kk=i;ll=j;
if(hw[i].d==){
for(;i<=j;i++){
if(hw[i].can>=)k++;
if(hw[i].can==)l++;
}
ans+=(long long)(k+l)*(k+l-)/;
ans+=(long long)k*(ll-kk+-l-k);
break;
}
while(){
if(hw[i].can)k++;i++;
if(hw[i].d!=hw[i-].d)break;
}
while(){
if(hw[j].can)l++;j--;
if(hw[j].d!=hw[j+].d)break;
}
ans+=(long long)k*(ll-j-l)+l*(i-kk-k)+k*l;i--;
}
}
if(w)map[zero]=;
return ans;
}
void dfs_ans(int now,int sum,int fa){
hw[++tot].d=sum;
hw[tot].can=map[zero+sum];
map[zero+sum]++;
for(int i=first[now];i;i=e[i].next)
if(e[i].to!=fa&&!vis[e[i].to])
dfs_ans(e[i].to,sum+e[i].d,now);
map[zero+sum]--;
}

从时间复杂度和代码量上都不如标解,唉,也难怪;

bzoj3697_FJ2014集训_采药人的路径_solution的更多相关文章

  1. 「FJ2014集训」采药人的路径

    啦啦啦 来写一篇题解 洛谷链接: P4930 「FJ2014集训」采药人的路径 统计路径?嗯往点分治上想. 把0和1转化为-1和1,求和完dis为0的路径就是阴阳平衡的路径了. 如果题目没有限制要有中 ...

  2. P4930「FJ2014集训」采药人的路径

    题目:P4930「FJ2014集训」采药人的路径 思路: 这篇不算题解,是让自己复习的,什么都没说清楚. 很久没有写点分治了,以前为了赶课件学的太急,板子都没打对就照着题解写题,导致学得很不扎实. 这 ...

  3. BZOJ_3697_采药人的路径_点分治

    BZOJ_3697_采药人的路径_点分治 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性 ...

  4. [bzoj3697]采药人的路径_点分治

    采药人的路径 bzoj-3697 题目大意:给你一个n个节点的树,每条边分为阴性和阳性,求满足条件的链的个数,使得这条链上阴性的边的条数等于阳性的边的条数,且这条链上存在一个节点,这个节点到一个端点的 ...

  5. 【BZOJ-3697&3127】采药人的路径&YinandYang 点分治 + 乱搞

    3697: 采药人的路径 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 681  Solved: 246[Submit][Status][Discus ...

  6. 改变Chrome浏览器主程序_缓存_个人信息路径

      改变Chrome浏览器缓存_个人信息路径(亲测) actionx2上传于2012-10-26|(7人评价)|3077人阅读|41次下载|文档简介|举报文档    在手机打开   改变 Chrom ...

  7. 【BZOJ3697】采药人的路径 点分治

    [BZOJ3697]采药人的路径 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是 ...

  8. bzoj千题计划248:bzoj3697: 采药人的路径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3697 点分治 路径0改为路径-1 g[i][0/1] 和 f[i][0/1]分别表示当前子树 和 已 ...

  9. 【BZOJ】【3697】采药人的路径&【3127】【USACO2013 Open】Yin and Yang

    点分治 Orz hzwer 倒是比较好想到点分治……然而在方案统计这里,我犯了两个错误…… 1.我比较傻逼的想的是:通过儿子来更新父亲,也就是统计以x为根的子树中xxxx的路径有多少条……这样转移. ...

随机推荐

  1. mysql常用日期、时间查询

    好记性不如烂笔头 select curdate(); --获取当前日期 select last_day(curdate()); --获取本月最后一天. day); -- 获取本月第一天 ,interv ...

  2. ubuntu16.04 安装 mysql-level

    ubuntu16.04 安装 mysql-level 1.下载 mysql-level(直接去官网下载rpm包,我的mysql-server是5.7.9.你下载自己对应的就可以了) 下载连接 2.rp ...

  3. /proc/xxx/maps简要记录

    定位内存泄漏基本上是从宏观到微观,进而定位到代码位置. 从/proc/meminfo可以看到整个系统内存消耗情况,使用top可以看到每个进程的VIRT(虚拟内存)和RES(实际占用内存),基本上就可以 ...

  4. FileRecv VNCViewer 使用方法

    版本 区别 一路点点点 . 就ok了 看到这个页面 点击   vnc viewer 输入 老师 会告诉你 IP地址  点击 就ok

  5. 洛谷 P2480 [SDOI2010]古代猪文 题解【欧拉定理】【CRT】【Lucas定理】

    数论综合题. 题目背景 题目背景与题目无关因此省略.题目链接 题目描述 猪王国的文明源远流长,博大精深. iPig 在大肥猪学校图书馆中查阅资料,得知远古时期猪文文字总个数为 \(N\).当然,一种语 ...

  6. Service Discovery protocol(SDP)

    locating services provided by Volume 3 , Part C , section 8 2.1sdp client-server architecture 2.2 se ...

  7. DB2 Package Issues and Solution

    Client 从 10.1 升级到11.1之后,而server端的DB 是10.1 版本,当客户执行sql语句时候报错: select * from ebcc.eol_item_info where ...

  8. Java学习之路(七):泛型

    泛型的概述和基本使用 作用:把类型明确的工作推前到创建对象或者调用方法的时候 泛型是一种参数化类型,把类型当做参数一样传递来明确集合的元素类型 泛型的好处 提高安全性 省去强转的麻烦 泛型的基本使用 ...

  9. php 如何匹配中文或英文姓名

    这几天在做项目的用户注册时,想限制用户使用一些比较奇怪的字符作为名字,即使用中文或者英文名字. 查了一些资料,例如:网友挥得更高的百度空间 写下了以下函数. //验证名字和密码 if (!preg_m ...

  10. php工具箱使用

    linux安装过程 1,去网盘下载(本人网盘也有,如果找不到,contact me)http://pan.baidu.com/s/1cxHQge 我解压以后放在/mnt/hgfs/root/phpto ...