传送门

题意:

路径有$-1,1$两种权值,求有多少路径满足权值和为$0$且有一个点将路径分成权值和为$0$的两段


第四节课本来想去上化学,然后快上课了这道题还没调出来.....可恶我想上化学

昨天两节语文课潸然的李煜讲座也没去听呜呜听说今天的语文课还有什么文艺活动又错过了呜呜

还是有思路的

点分治,考虑经过$u$的路径

首先保证权值和为$0$,记录$c[i]$为当前权值和为$i$的路径有几条

怎么满足有一个点呢?

$0+0=0$!!!

我们只要保证一段和$0$另一段自然也是$0$

所以补充保存的信息,

$c[i][0]$当前权值和为$0$且到$u$的路径上没有一段为$0$(就是没有祖先的权值和也为$i$,打标记就行了)的路径有几条

$c[i][1]$表示有......

然后每颗子树先更新答案再更新$c$就行了

然后一直$WA$.....

突然想到自己没有处理$u$的信息

然后改了也不对

然后发现打标记只是$=1\ =0$没有$++\ --$.....

改了还不对

参考黄学长的代码打了一份他的做法$AC$了,然后又开始找自己的错误

最后还是处理$u$的信息有问题,我直接用了$mark$因为我还以为$mark$只有$0,1$.......

还我化学

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+,INF=1e9+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,a,b,w;
struct edge{
int v,w,ne;
}e[N<<];
int h[N],cnt;
inline void ins(int u,int v,int w){
cnt++;
e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].w=w;e[cnt].ne=h[v];h[v]=cnt;
} int f[N],size[N],all,vis[N],root;
void dfsRt(int u,int fa){
size[u]=;f[u]=;
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(vis[v]||v==fa) continue;
dfsRt(v,u);
size[u]+=size[v];
f[u]=max(f[u],size[v]);
}
f[u]=max(f[u],all-size[u]);
if(f[u]<f[root]) root=u;
}
int mark[N<<],Z=N,c[N<<][];
ll ans;
void dfsAns(int u,int fa,int now){
if(now==) ans+=c[Z][]+c[Z][] +(mark[Z]>=);
else{
if(mark[Z+now]) ans+=c[Z-now][]+c[Z-now][];
else ans+=c[Z-now][];
}
mark[Z+now]++;
for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v]&&e[i].v!=fa) dfsAns(e[i].v,u,now+e[i].w);
mark[Z+now]--;
}
int st[N],top;
void dfsDee(int u,int fa,int now){
c[Z+now][mark[Z+now]>=]++;
st[++top]=Z+now;
mark[Z+now]++;
for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v]&&e[i].v!=fa) dfsDee(e[i].v,u,now+e[i].w);
mark[Z+now]--;
}
void dfsSol(int u){
vis[u]=;
for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v]) dfsAns(e[i].v,u,e[i].w),dfsDee(e[i].v,u,e[i].w); while(top) c[st[top]][]=c[st[top]][]=,top--;
for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v]){
all=size[e[i].v];root=;
dfsRt(e[i].v,);
dfsSol(root);
}
}
int main(){
freopen("in","r",stdin);
n=read();
for(int i=;i<n;i++) a=read(),b=read(),w= read()==?-:,ins(a,b,w);
all=n;root=;f[]=INF;
dfsRt(,);
dfsSol(root);
printf("%lld",ans);
}

黄学长做法,本质上一样的

改进了一下后$1600ms$

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+,INF=1e9+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,a,b,w;
struct edge{
int v,w,ne;
}e[N<<];
int h[N],cnt;
inline void ins(int u,int v,int w){
cnt++;
e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].w=w;e[cnt].ne=h[v];h[v]=cnt;
} int f[N],size[N],all,vis[N],root;
void dfsRt(int u,int fa){
size[u]=;f[u]=;
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(vis[v]||v==fa) continue;
dfsRt(v,u);
size[u]+=size[v];
f[u]=max(f[u],size[v]);
}
f[u]=max(f[u],all-size[u]);
if(f[u]<f[root]) root=u;
}
int mark[N<<],Z=N;
ll c[N<<][],d[N<<][];
ll ans;
int mx;
void dfsRun(int u,int fa,int now){
d[Z+now][mark[Z+now]>=]++;
mx=max(mx,abs(now));
mark[Z+now]++;
for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v]&&e[i].v!=fa)
dfsRun(e[i].v,u,now+e[i].w);
mark[Z+now]--;
}
void dfsSol(int u){//printf("dfsSol %d\n",u);
vis[u]=;
c[Z][]=;
int mxmx=;
for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v]){
mx=;
dfsRun(e[i].v,u,e[i].w);
mxmx=max(mxmx,mx);
ans+=(c[Z][]-)*d[Z][];
for(int j=-mx;j<=mx;j++)
ans+=c[Z-j][]*d[Z+j][]+
c[Z-j][]*d[Z+j][]+c[Z-j][]*d[Z+j][];
for(int j=Z-mx;j<=Z+mx;j++){
c[j][]+=d[j][];
c[j][]+=d[j][];
d[j][]=d[j][]=;
}
}
for(int i=Z-mxmx;i<=Z+mxmx;i++) c[i][]=c[i][]=;
for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v]){
all=size[e[i].v];root=;
dfsRt(e[i].v,);
dfsSol(root);
}
}
int main(){
freopen("in","r",stdin);
n=read();
for(int i=;i<n;i++) a=read(),b=read(),w= read()==?-:,ins(a,b,w);
all=n;root=;f[]=INF;
dfsRt(,);
dfsSol(root);
printf("%lld",ans);
}

BZOJ 3697: 采药人的路径 [点分治] [我想上化学课]的更多相关文章

  1. BZOJ 3697: 采药人的路径 点分治

    好久不做点分治的题了,正好在联赛之前抓紧复习一下. 先把边权为 $0$ 的置为 $-1$.定义几个状态:$f[dis][0/1],g[dis][0/1]$ 其中 $f$ 代表在当前遍历的子树内的答案. ...

  2. bzoj 3697: 采药人的路径【点分治】

    点分治,设当前处理的块的重心为rt,预处理出每个子树中f[v][0/1]表示组合出.没组合出一对值v的链数(从当前儿子出发的链),能组合出一对v值就是可以有一个休息点 然后对于rt,经过rt且合法的路 ...

  3. [BZOJ 3697] 采药人的路径

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3697 [算法] 首先 , 将黑色的边变成1 ,白色的边变成-1 那么 , 问题就转化 ...

  4. 【BZOJ】3697: 采药人的路径

    3697: 采药人的路径 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1718  Solved: 602[Submit][Status][Discu ...

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

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

  6. BZOJ 3697/3127 采药人的路径 (点分治)

    题目大意: 从前有一棵无向树,树上边权均为$0$或$1$,有一个采药人,他认为如果一条路径上边权为$0$和$1$的边数量相等,那么这条路径阴阳平衡.他想寻找一条合法的采药路径,保证阴阳平衡.然后他发现 ...

  7. BZOJ.3784.树上的路径(点分治 贪心 堆)

    BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...

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

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

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

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

随机推荐

  1. HDU--2011

    多项式求和 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  2. linux下vi编辑某文件时,操作出现 错误提示: E325: ATTENTION 2, Found a swap file by the name ".p1.c.swp"

    当我在linux下用vi打开p1.c文件时 root@iZ2zeeailqvwws5dcuivdbZ:~/1/01/指针# vi p1.c 会出现如下信息: E325: ATTENTION Found ...

  3. 在虚拟机(VMware)中安装Linux CentOS 6.4系统(图解) 转

    一.下载最新版本Linux CentOS     1.打开官网地址:http://www.centos.org/,点击Downloads->Mirrors         2.点击CentOS ...

  4. jQuery:图片自动变换

    <script type="text/javascript"> var aa=0; //设置变换时间为2s var timeChange=2000; //定义数组 va ...

  5. js立体旋转展示效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. destoon分页

    <?php //控制分页//分页$pagesize=4;$pagesql="SELECT COUNT(*) AS num FROM `{$DT_PRE}` company"; ...

  7. Moogoose Constructor小坑

    注意! exports 出来的 Model名字,必须和 Constructor的名字不一样!!! 不然Constructor会被覆盖,报错 这个是修改之后的.修改前,是var account = ne ...

  8. C#总结(四)调用C++动态库

    由于公司很多底层的SDK,都是C++开发,上层的应用软件却是C# Winform程序.在实际工作的过程中,就经常碰到了C# 程序调用C++ 动态库的问题.最近一直在和C++ 打交道,C# 怎么调用C+ ...

  9. nginx添加编译lua模块

    一 .安装LuaJit 1.下载LuaJit # wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz 2.编译安装 # tar xzvf LuaJI ...

  10. 腾讯工程师带你深入解析 MySQL binlog

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 本文由 腾讯云数据库内核团队 发布在云+社区 1.概述 binlog是Mysql sever层维护的一种二进制日志,与innodb引擎中的red ...