传送门

不是那么裸的点分治。

$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. (二十三)原型模式详解(clone方法源码的简单剖析)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 原型模式算是JAVA中最简单 ...

  2. DataGridView 绑定List集合后实现自定义排序

    这里只贴主要代码,dataList是已添加数据的全局变量,绑定数据源 datagridview1.DataSource = dataList,以下是核心代码. 实现点击列表头实现自定义排序 priva ...

  3. [转]MyBatis传入多个参数的问题 - mingyue1818

    原文  http://www.cnblogs.com/mingyue1818/p/3714162.html 一.单个参数: public List<XXBean> getXXBeanLis ...

  4. Yii2 使用小部件 Breadcrumbs

    yii有两种Breadcrumbs写法,one: echo Breadcrumbs::widget([ 'itemTemplate' => "<li><i>{l ...

  5. 获取 AlertDialog自定义的布局 的控件

    AlertDialog自定义的布局 效果图: 创建dialog方法的代码如下: 1 LayoutInflater inflater = getLayoutInflater(); 2 View layo ...

  6. [转] java中int,char,string三种类型的相互转换

    原文地址:http://blog.csdn.net/lisa0220/article/details/6649707 如何将字串 String 转换成整数 int? int i = Integer.v ...

  7. 【转】oracle数据库开发的一些经验积累

    1.不安装Oracle客户连接Oracle 8的方法  请将以下文件拷贝到运行文件所在目录 一.ODBC动态库 : ctl3d32.dll msvcrt40.dll odbc16gt.dll odbc ...

  8. 常用免费的WebService列表

    天气预报Web服务,数据来源于中国气象局 Endpoint :     http://www.webxml.com.cn/WebServices/WeatherWebService.asmx Disc ...

  9. HashMap Hashtable区别

    http://blog.csdn.net/java2000_net/archive/2008/06/05/2512510.aspx 我们先看2个类的定义 public class Hashtable ...

  10. 安装完ActivePython后Python的Idle窗口打不开也卸载不掉的解决方法

    1.想找一个好的PythonIDE开发环境所以就安装了ActivePython开发公具,结果发现软件打不开,机器上装的Python环境也不能用了,网上相关的解决方法也是寥寥无几...真悲催! 2.后来 ...