传送门

不是那么裸的点分治。

$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. 谈谈关于Python里面小数点精度控制的问题

    基础 浮点数是用机器上浮点数的本机双精度(64 bit)表示的.提供大约17位的精度和范围从-308到308的指数.和C语言里面的double类型相同.Python不支持32bit的单精度浮点数.如果 ...

  2. HTML5之创新的视频拼图剖析式学习之二

    昨天我们剖析了一下翻阅体验的实现.今天要剖析另外一个很有意思的效果——视频拼图. 网站中第一部分第二页<月熊的标志>是月熊志中互动性较强的一页,页面上会随机分布9块视频碎片,用户可以通过鼠 ...

  3. angular一些冷门的用法

    1.controller的第三个参数

  4. [Offer收割]编程练习赛5-1 小Ho的防护盾

    #1357 : 小Ho的防护盾 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho的虚拟城市正在遭受小Hi的攻击,小Hi用来攻击小Ho城市的武器是一艘歼星舰,这艘歼星 ...

  5. C 语言学习的第 01 课:先来聊聊计算机吧

    各位同学,新学期,我就是你们的助教了.我的个人信息,你们的任课老师都已经介绍过了,所以我这里也就不再啰嗦.下面,来聊聊今天的话题:“先来谈谈计算机吧”. 想必看到这个题目,你们大家一定是不愿意点击进来 ...

  6. ubuntu-16.4TLS安装QQ

    01下载Winqq 下载地址:http://www.ubuntukylin.com/application/show.php?lang=cn&id=27902解压zip unzip wine- ...

  7. python 之禅

    想要真正深入了解一门语言,需要用心去感受.下面是python之禅,python的设计哲学,对于编程很有指导意义.(翻译部分摘自网络,同时自己有一些更改) >>> import thi ...

  8. Android布局方式_RelativeLayout

    RelativeLayout(相对布局)允许子元素指定它们相对于其他元素或父元素的位置(通过ID指定),因此用户可以右对齐,或上下对齐,或置于屏幕中央的形式来排列两个元素. RelativeLayou ...

  9. [转]html js中name和id的区别和使用分析

    js中web页面元素的调用可以有两种识别方法:id和name 自己在用的过程中总结一下id和name的使用区别. 一,使用范围 除 BASE, HEAD, HTML, META, SCRIPT, ST ...

  10. swift 学习(一)基础知识 (基本数据类型,操作符,流控制,集合)

    xcode 中调用API帮助 1.查看简单信息,选中后 按键 control +左键单击  或者按 右侧属性栏 里的帮助按钮 2.完整API,选中后 按键 control +左键双击 3.查看类.函数 ...