BZOJ 3697: 采药人的路径 [点分治] [我想上化学课]
题意:
路径有$-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: 采药人的路径 [点分治] [我想上化学课]的更多相关文章
- BZOJ 3697: 采药人的路径 点分治
好久不做点分治的题了,正好在联赛之前抓紧复习一下. 先把边权为 $0$ 的置为 $-1$.定义几个状态:$f[dis][0/1],g[dis][0/1]$ 其中 $f$ 代表在当前遍历的子树内的答案. ...
- bzoj 3697: 采药人的路径【点分治】
点分治,设当前处理的块的重心为rt,预处理出每个子树中f[v][0/1]表示组合出.没组合出一对值v的链数(从当前儿子出发的链),能组合出一对v值就是可以有一个休息点 然后对于rt,经过rt且合法的路 ...
- [BZOJ 3697] 采药人的路径
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3697 [算法] 首先 , 将黑色的边变成1 ,白色的边变成-1 那么 , 问题就转化 ...
- 【BZOJ】3697: 采药人的路径
3697: 采药人的路径 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1718 Solved: 602[Submit][Status][Discu ...
- 【BZOJ3697】采药人的路径 点分治
[BZOJ3697]采药人的路径 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是 ...
- BZOJ 3697/3127 采药人的路径 (点分治)
题目大意: 从前有一棵无向树,树上边权均为$0$或$1$,有一个采药人,他认为如果一条路径上边权为$0$和$1$的边数量相等,那么这条路径阴阳平衡.他想寻找一条合法的采药路径,保证阴阳平衡.然后他发现 ...
- BZOJ.3784.树上的路径(点分治 贪心 堆)
BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...
- BZOJ3697采药人的路径——点分治
题目描述 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径 ...
- BZOJ3697:采药人的路径(点分治)
Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药 ...
随机推荐
- 去除FineReport报表点击单元格时出现的黑框
选择模版->模版web属性 添加加载结束事件,具体代码如下 $("td").bind("click",function(){return false;}) ...
- hadoop2.6.0集群搭建
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- 【Zigbee技术入门教程-01】Zigbee无线组网技术入门的学习路线
[Zigbee技术入门教程-01]Zigbee无线组网技术入门的学习路线 广东职业技术学院 欧浩源 一.引言 在物联网技术应用的知识体系中,Zigbee无线组网技术是非常重要的一环,也是大家感 ...
- python爬虫知乎
在之前写过一篇使用python爬虫爬取电影天堂资源的博客,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...
- Java中 equals() 和 == 的区别
1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的 "值"是否相等: 如果作用于引用类型的变量,则比较的是所指向的对象的地址 2)对于equals方法,注意:equal ...
- Angular19 自定义表单控件
1 需求 当开发者需要一个特定的表单控件时就需要自己开发一个和默认提供的表单控件用法相似的控件来作为表单控件:自定义的表单控件必须考虑模型和视图之间的数据怎么进行交互 2 官方文档 -> 点击前 ...
- java虚拟机和java内存区域概述
什么是虚拟机,什么是Java虚拟机 虚拟机 定义:模拟某种计算机体系结构,执行特定指令集的软件 系统虚拟机(Virtual Box.VMware),进程虚拟机 进程虚拟机 jvm.Adobe Flas ...
- PHP的CI框架流程基本熟悉
CI框架是PHP的一个快速开发框架,我是目前的公司项目后台语言用的PHP,因为我做前端开发,需要用php去填充页面数据,所以就开始去了解这个框架,学习了一些php和数据库的东西,这篇文章先具体介绍CI ...
- Android 使用EventBus发送消息接收消息
基本使用 自定义一个类 public class LoginEvent { private String code;//是否成功 public LoginEvent(String code) { th ...
- JavaScript动画:offset家族和匀速动画详解(含轮播图的实现)
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. offset家族简介 我们知道,三大家族包括:offset/scroll ...