洛谷题目传送门

闲话

偶然翻到一道没有题解的淀粉质,想证明一下自己是真的弱

然而ZSYC(字符串组合)早就切了

然后证明成功了,WA到怀疑人生,只好借着ZSY的代码拍,拍了几万组就出来了。。。

思路

是人都能想到的:路径统计,点分治跑不了了。

然而这个统计有些麻烦。。。

首先别看错题,是中间的一个点到两个端点的两条路径都要满足黑白相等。(因为蒟蒻就看错了)

显然,我们每次要统计经过重心的路径,但是这个中点不一定会在重心。于是,必须要更一般化地统计了。

容易想到的是差分。记\(d_x\)为\(x\)到重心路径上黑白个数的差,可以改一下边权变成\(1\)和\(-1\),更好实现。

这时候,我们已经可以做到统计黑白个数相等的路径了,一对差分值为\(d\)和\(-d\)的路径就可以产生贡献。

但是,题目要两条子路径都黑白相等啊!再想想,假设有两个点\(x,y,d_x=-d_y\),那么是不是只有在\(x\)的祖先中存在\(z\)且\(d_z=-d_y\),或者在\(y\)的祖先中存在\(z\)且\(d_x=-d_z\),路径\(x-y\)才能贡献答案?

这也就是说,我们选择的中点\(z\)的\(d\)值,需要和\(d_x\)或\(d_y\)相等才行。

于是,我们根据每个点是否有祖先的\(d\)等于它的\(d\),分成两类。显然,没有的点只能和有的点算贡献,而有的点可以和两种点都算贡献。开两个桶区别统计一下就好了。

具体实现的话,蒟蒻直接依次枚举重心的子树,先统计一个子树的答案,再把子树的每个点丢进桶里。这样就不用容斥去除不合法情况了。但是要特判一个端点在重心上的路径的贡献。

如何快速判断当前点的属于哪一类?开一个数组\(b\)统计祖先中每个\(d\)值出现的次数就可以了(\(d\)可能是负数,要把所有下标加\(n\))。注意回溯的时候要减掉。

注意答案要开long long,注意清空数组。

代码算是很短的了。

#include<cstdio>
#include<cstring>
#define RG register
#define R RG int
#define G c=getchar()
const int N=1e5+1,M=N<<1;
int n,rt,mx,mn,he[N],ne[M],to[M],c[M],s[N],m[N],b[M],f[M],g[M];
bool vis[N];
long long ans;
inline void min(R&x,R y){if(x>y)x=y;}
inline void max(R&x,R y){if(x<y)x=y;}
inline int in(){
RG char G;
while(c<'-')G;
R x=c&15;G;
while(c>'-')x=x*10+(c&15),G;
return x;
}
void dfs(R x){//求重心
vis[x]=1;s[x]=1;m[x]=0;
for(R y,i=he[x];i;i=ne[i])
if(!vis[y=to[i]])
dfs(y),s[x]+=s[y],max(m[x],s[y]);
max(m[x],n-s[x]);
if(m[rt]>m[x])rt=x;
vis[x]=0;
}
void upd(R x,R d){//统计答案,f没有g有
min(mn,d);max(mx,d);
ans+=g[M-d];//分类贡献
if(b[d])ans+=f[M-d];
if(d==N)ans+=b[d]>1;//特判
vis[x]=1;++b[d];
for(R i=he[x];i;i=ne[i])
if(!vis[to[i]])upd(to[i],d+c[i]);
vis[x]=0;--b[d];//回溯清零
}
void mdf(R x,R d){//修改桶
++(b[d]?g[d]:f[d]);
vis[x]=1;++b[d];
for(R i=he[x];i;i=ne[i])
if(!vis[to[i]])mdf(to[i],d+c[i]);
vis[x]=0;--b[d];
}
void div(R x){//分治
rt=0;dfs(x);x=rt;
vis[x]=1;b[mn=mx=N]=1;//此处注意初始化
R t=n,y,i;
for(i=he[x];i;i=ne[i])
if(!vis[y=to[i]])
upd(y,N+c[i]),mdf(y,N+c[i]);
memset(f+mn,0,(mx-mn+1)<<2);//注意清空
memset(g+mn,0,(mx-mn+1)<<2);
for(i=he[x];i;i=ne[i])
if(!vis[y=to[i]])
n=s[x]>s[y]?s[y]:t-s[x],div(y);
}
int main(){
m[0]=1e9;n=in();
for(R a,b,p=0,i=1;i<n;++i){
a=in();b=in();
ne[++p]=he[a];to[he[a]=p]=b;
ne[++p]=he[b];to[he[b]=p]=a;
c[p]=c[p-1]=in()?1:-1;//处理边权
}
div(1);
printf("%lld\n",ans);
return 0;
}

洛谷P3085 [USACO13OPEN]阴和阳Yin and Yang(点分治,树上差分)的更多相关文章

  1. 洛谷P3348 [ZJOI2016]大森林(LCT,虚点,树上差分)

    洛谷题目传送门 思路分析 最简单粗暴的想法,肯定是大力LCT,每个树都来一遍link之类的操作啦(T飞就不说了) 考虑如何优化算法.如果没有1操作,肯定每个树都长一样.有了1操作,就来仔细分析一下对不 ...

  2. 【洛谷 P2633】 Count on a tree(主席树,树上差分)

    题目链接 思维难度0 实现难度7 建出主席树后用两点的状态减去lca和lca父亲的状态,然后在新树上跑第\(k\)小 #include <cstdio> #include <cstr ...

  3. 洛谷P3345 [ZJOI2015]幻想乡战略游戏(动态点分治,树的重心,二分查找,Tarjan-LCA,树上差分)

    洛谷题目传送门 动态点分治小白,光是因为思路不清晰就耗费了不知道多少时间去gang这题,所以还是来理理思路吧. 一个树\(T\)里面\(\sum\limits_{v\in T} D_vdist(u,v ...

  4. 洛谷.4115.Qtree4/BZOJ.1095.[ZJOI2007]Hide捉迷藏(动态点分治 Heap)

    题目链接 洛谷 SPOJ BZOJ1095(简化版) 将每次Solve的重心root连起来,会形成一个深度为logn的树,就叫它点分树吧.. 我们对每个root维护两个东西: 它管辖的子树中所有白点到 ...

  5. Bzoj1202/洛谷P2294 [HNOI2005]狡猾的商人(带权并查集/差分约束系统)

    题面 Bzoj 洛谷 题解 考虑带权并查集,设\(f[i]\)表示\(i\)的父亲(\(\forall f[i]<i\)),\(sum[i]\)表示\(\sum\limits_{j=fa[i]} ...

  6. 洛谷 P5502 - [JSOI2015]最大公约数(区间 gcd 的性质+分治)

    洛谷题面传送门 学校模拟赛的某道题让我联想到了这道题-- 先讲一下我的野鸡做法. 首先考虑分治,对于左右端点都在 \([L,R]\) 中的区间我们将其分成三类:完全包含于 \([L,mid]\) 的区 ...

  7. 洛谷 P3084 [USACO13OPEN]照片Photo 解题报告

    [USACO13OPEN]照片Photo 题目描述 农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\) ...

  8. 洛谷 P2209 [USACO13OPEN]燃油经济性Fuel Economy

    P2209 [USACO13OPEN]燃油经济性Fuel Economy 题目描述 Farmer John has decided to take a cross-country vacation. ...

  9. 洛谷3084 [USACO13OPEN]照片Photo

    原题链接 神仙\(DP\)啊... 题解请移步隔壁大佬的博客\(QAQ\) #include<cstdio> using namespace std; const int N = 2e5 ...

随机推荐

  1. Maven学习笔记-04-Eclipse下maven项目在Tomcat7和Jetty6中部署调试

    现在最新的Eclipse Luna Release 已经内置了Maven插件,这让我们的工作简洁了不少,只要把项目直接导入就可以,不用考虑插件什么的问题,但是导入之后的项目既可以部署在Tomcat也可 ...

  2. linux svn代码回滚命令

    取消对代码的修改分为两种情况: 第一种情况:改动没有被提交(commit). 这种情况下,使用svn revert就能取消之前的修改. svn revert用法如下: # svn revert [-R ...

  3. Flask-sqlalchemy 语法总结

    Flask-sqlalchemy 语法总结 ** DDLdb.create_all() :创建实体表db.drop_all(): 删除表 1)插入表Db.session.add(user) #user ...

  4. Quartz.net 定时任务之储存与持久化和集群(源码)

    一.界面 1.这篇博客不上教程.直接看结果(包括把quartz任务转换成Windows服务) (1).主界面 (2).添加任务(默认执行) (3).编辑(默认开启) (4).关闭和开启 2.代码说明 ...

  5. slurm用户快速入门手册

    1. 概述2. 架构3. 命令3.1 sacct3.2 sattach3.4 sbatch3.5 sbcast3.6 scancel3.7 scontrol3.8 sinfo3.9 smap3.10 ...

  6. BugkuCTF 计算器

    前言 写了这么久的web题,算是把它基础部分都刷完了一遍,以下的几天将持续更新BugkuCTF WEB部分的题解,为了不影响阅读,所以每道题的题解都以单独一篇文章的形式发表,感谢大家一直以来的支持和理 ...

  7. 类似于PLC上升沿的TRIO代码示例

    需求:    一个自复位按钮,控制灯泡的亮与灭(按钮按一次灯亮,再按一次灯灭依次循环). 简短的代码,若大家有更好的思路可以评论区留言. DIM in_button,op_lamp,var_middl ...

  8. Jumpserver双机高可用环境部署笔记

    之前在IDC部署了Jumpserver堡垒机环境,作为登陆线上服务器的统一入口.后面运行一段时间后,发现Jumpserver服务器的CPU负载使用率高达80%以上,主要是python程序对CPU的消耗 ...

  9. Flask、Celery、RabbitMQ学习计划

    Flask (9.16-9.23) 相关组件了解 (9.16-17) WSGI:Werkzeug 数据库:SQLAlchemy   *重点查看 urls和视图 (9.18-19) session和co ...

  10. Asp.net框架与SpringMvc框架简单分析

    (此文为自我总结,错误很多请勿借鉴) 1.就前两天分析SpringMvc框架中是通过controler来实现跳转页面,通过mapping来实现数据连接 分析的方法又通过java的类之间进行相互调用,个 ...