传送门

不是那么裸的点分治。

$f[i][0/1]$表示当前节点的一个子树中总权值和为$i$,且是否存在一个前缀使得其前缀和为$i$

$g[i][0/1]$表示当前节点的已遍历过的子树,其余一样。

对于每个节点

$ans_{node}=g[0][0]∗f[0][0]+ \sum (g[−i][0]∗f[i][1]+g[−i][1]∗f[i][0]+g[−i][1]∗f[i][1])$

另外,Race那道题选根的方案在这里好像不是很适用,容易出问题,还是换黄学长的比较好。

 //BZOJ 3697
 //by Cydiater
 //2016.9.26
 #include <iostream>
 #include <cstdio>
 #include <cstring>
 #include <string>
 #include <algorithm>
 #include <queue>
 #include <map>
 #include <ctime>
 #include <cmath>
 #include <iomanip>
 #include <cstdlib>
 using namespace std;
 #define ll long long
 #define up(i,j,n)       for(int i=j;i<=n;i++)
 #define down(i,j,n)     for(int i=j;i>=n;i--)
 ;
 const int oo=0x3f3f3f3f;
 inline int read(){
     ,f=;
     ;ch=getchar();}
     +ch-';ch=getchar();}
     return x*f;
 }
 ,sum,root,siz[MAXN],dis[MAXN],pre[MAXN],deep[MAXN];
 int maxdeep,max_siz[MAXN];
 ll ans=,f[MAXN][],g[MAXN][];
 bool vis[MAXN];
 struct edge{
     int y,next,v;
 }e[MAXN];
 namespace solution{
     inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;}
     void init(){
         N=read();
         up(i,,N){
             ll x=read(),y=read(),v=read()==?-:;
             insert(x,y,v);
             insert(y,x,v);
         }
     }
     void make_root(int node,int fa){
         max_siz[node]=;siz[node]=;
         for(int i=LINK[node];i;i=e[i].next)if(!vis[e[i].y]&&e[i].y!=fa){
             make_root(e[i].y,node);
             siz[node]+=siz[e[i].y];
             max_siz[node]=max(max_siz[node],siz[e[i].y]);
         }
         max_siz[node]=max(max_siz[node],sum-max_siz[node]);
         if(max_siz[node]<max_siz[root])root=node;
     }
     void dfs(int node,int father){
         ]++;
         ]++;
         pre[dis[node]]++;
         maxdeep=max(deep[node],maxdeep);
         for(int i=LINK[node];i;i=e[i].next)
             if(e[i].y!=father&&!vis[e[i].y]){
                 deep[e[i].y]=deep[node]+;
                 dis[e[i].y]=dis[node]+e[i].v;
                 dfs(e[i].y,node);
             }
         pre[dis[node]]--;
     }
     void work(int node){
         vis[node]=;g[N][]=;;
         for(int i=LINK[node];i;i=e[i].next)if(!vis[e[i].y]){
             dis[e[i].y]=e[i].v+N;deep[e[i].y]=;maxdeep=;
             dfs(e[i].y,);mx=max(mx,maxdeep);
             ans+=1LL*(g[N][]-)*f[N][];
             up(k,-maxdeep,maxdeep)
                 ans+=1LL*g[N-k][]*f[N+k][]+1LL*g[N-k][]*f[N+k][]+1LL*g[N-k][]*f[N+k][];
             up(j,N-maxdeep,N+maxdeep){
                 g[j][]+=f[j][];
                 g[j][]+=f[j][];
                 f[j][]=f[j][]=;
             }
         }
         up(j,N-mx,N+mx)g[j][]=g[j][]=;
         for(int i=LINK[node];i;i=e[i].next)if(!vis[e[i].y]){
             root=;sum=siz[e[i].y];
             make_root(e[i].y,);
             work(root);
         }
     }
     void slove(){
         sum=N;root=;max_siz[root]=N;
         make_root(,);
         work(root);
     }
     void output(){
         cout<<ans<<endl;
     }
 }
 int main(){
     //freopen("input.in","r",stdin);
     using namespace solution;
     init();
     slove();
     output();
     ;
 }

BZOJ3697: 采药人的路径的更多相关文章

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

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

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

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

  3. BZOJ3697采药人的路径——点分治

    题目描述 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径 ...

  4. BZOJ3697:采药人的路径(点分治)

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

  5. [bzoj3697]采药人的路径——点分治

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

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

    题目 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药活动.他选择的路径 ...

  7. BZOJ3697: 采药人的路径(点分治)

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

  8. 2019.01.09 bzoj3697: 采药人的路径(点分治)

    传送门 点分治好题. 题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数. 思路: 考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数 ...

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

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

随机推荐

  1. HTML5+JS 《五子飞》游戏实现(一)规则

    很久没写文章了,这个游戏其实已经写了有段时间了,一直没有完善,赶在新年之际,分享给大家. 该<五子飞>游戏,不是平常大家所说的<五子棋>,这个玩法简单,是我们老家儿时常玩的一种 ...

  2. Android开发自学笔记(Android Studio1.3.1)—3.Android应用结构解析

    一.R文件是什么?      如上图所示,我们可以通过findViewById方法通过传入R.id.show找到我们的TextView元素,findViewById方法也很好理解,从View中通过Id ...

  3. 使用 Eclipse 调试 Java 程序的技巧

    你应该看过一些如<关于调试的N件事>这类很流行的帖子 .假设我每天花费1小时在调试我的应用程序上的话,那累积起来的话也是很大量的时间.由于这个原因,用这些时间来重视并了解所有使我们调试更方 ...

  4. EditPlus v4.5 简体中文

    优秀的代码编辑器! 下载地址: EditPlus v4.00 build 465 简体中文汉化增强版 http://yunpan.cn/cVCSIZsKK7VFF    访问fe58 http://p ...

  5. Linq的TakeWhile误用

    where(func<>)返回符合条件的元素 与此相对的skipwhile跳过符合条件的,返回剩下的元素 容易误用的takewhile,与where 不一样,只有当所有元素满足条件时,才返 ...

  6. 由Nullable模式想到的ToString的扩展

    虽然关于null的一切争论永不停息,但根据实际开发经历,很多时候需要判断无聊的null,并且有些的判断是可有可无的,尤其是在表现层. string e = null; if (e != null) { ...

  7. android开发------初识Activity

    之前我们简单说过,Activity实际上是一个窗体,用来存放我们的程序外观. 我们先来创建一个空的Activity,不加载任何layout.要做的是,定义自己的类,继承android的Activity ...

  8. extJs学习基础2

    一个登陆界面: Ext.onReady(function(){ Ext.define('Login', { //renderTo: Ext.getBody(), extend: 'Ext.window ...

  9. display~

  10. 【UOJ #29】【IOI 2014】holiday

    http://uoj.ac/problem/29 cdq四次处理出一直向左, 一直向右, 向左后回到起点, 向右后回到起点的dp数组,最后统计答案. 举例:\(fi\)表示一直向右走i天能参观的最多景 ...