https://www.luogu.org/problemnew/show/P1600

(仅做记录)

自己的假方法:

每一次跑从a到b:
设l=lca(a,b)
对于以下产生贡献:

a到l的链上所有的点(x)满足
dep[x]+w[x]==dep[a]

l到b的链上(不含l)所有的点(x)满足
dep[x]-dep[l]+dep[a]-dep[l]==w[x]
即dep[x]-w[x]==2*dep[l]-dep[a]

于是每一个点记两个map<int,int>,其中键值对(p,q)表示

“从该点到根的路径上所有满足 dep[x]+w[x]==p(第一个map) / dep[x]-w[x]==p(第二个map) 的点的答案都要加上q"

每一次跑,就是树上差分,乱搞一下。。。

最后每个点x的答案就是以其为根的子树中所有点的两个map分别合并起来后(两个map里面分别有(p,q1)和(p,q2),则合并后有(p,q1+q2)),

在这两个map里面分别查询dep[x]+w[x]和dep[x]-w[x]得到答案的和

因此可以启发式合并处理一下

把平衡树换成值域线段树,启发式合并换成线段树合并就是一个log了。。。。。

曾经错误:线段树节点作死不开垃圾回收,空间可能算不太对了,原来开7000000都RE了

 #include<cstdio>
#include<algorithm>
using namespace std;
int ll=-,rr=;
namespace SegT
{
int dat[],lc[],rc[],mem;
int L,x;
#define mid (l+((r-l)>>1))
void _addx(int l,int r,int &num)
{
if(!num) num=++mem;
if(l==r) {dat[num]+=x;return;}
if(L<=mid) _addx(l,mid,lc[num]);
else _addx(mid+,r,rc[num]);
dat[num]=dat[lc[num]]+dat[rc[num]];
}
int merge(int a,int b)
{
if(!a||!b) return a+b;
dat[a]+=dat[b];
lc[a]=merge(lc[a],lc[b]);
rc[a]=merge(rc[a],rc[b]);
//delnode(b)
return a;
}
int _query(int l,int r,int num)
{
if(l==r) return dat[num];
if(L<=mid) return _query(l,mid,lc[num]);
else return _query(mid+,r,rc[num]);
}
void addx(int pos,int dat,int &num)
{
L=pos;x=dat;_addx(ll,rr,num);
}
int query(int pos,int &num)
{
L=pos;return _query(ll,rr,num);
}
#undef mid
}
using SegT::addx;using SegT::query;using SegT::merge;
struct E
{
int to,nxt;
}e[];
int f1[],ne;
int w[],rt1[],rt2[];
int n,m;
namespace LCA
{
int anc[][],log2n,dep[];
void dfs(int u,int fa)
{
int i,k;
anc[u][]=fa;
for(i=;i<=log2n;i++) anc[u][i]=anc[anc[u][i-]][i-];
for(k=f1[u];k;k=e[k].nxt)
if(e[k].to!=fa)
{
dep[e[k].to]=dep[u]+;
dfs(e[k].to,u);
}
}
int lca(int a,int b)
{
if(dep[a]<dep[b]) swap(a,b);
int t=dep[a]-dep[b],i;
for(i=log2n;i>=;i--)
if((<<i)<=t)
t-=(<<i),a=anc[a][i];
if(a==b) return a;
for(i=log2n;i>=;i--)
if(anc[a][i]!=anc[b][i])
a=anc[a][i],b=anc[b][i];
return anc[a][];
}
}
using LCA::lca;using LCA::dep;
int ans[];
void dfs(int u,int fa)
{
int k;
for(k=f1[u];k;k=e[k].nxt)
if(e[k].to!=fa)
{
dfs(e[k].to,u);
rt1[u]=merge(rt1[u],rt1[e[k].to]);
rt2[u]=merge(rt2[u],rt2[e[k].to]);
}
ans[u]=query(dep[u]+w[u],rt1[u])+query(dep[u]-w[u],rt2[u]);
}
int main()
{
int i,a,b,l;
scanf("%d%d",&n,&m);
for(i=;i<n;i++)
{
scanf("%d%d",&a,&b);
e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;
e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;
}
for(i=;i<=n;i++) scanf("%d",&w[i]);
while((<<(LCA::log2n+))<=n) LCA::log2n++;
LCA::dfs(,);
while(m--)
{
scanf("%d%d",&a,&b);l=lca(a,b);
addx(dep[a],,rt1[a]);addx(dep[a],-,rt1[LCA::anc[l][]]);
addx(*dep[l]-dep[a],,rt2[b]);addx(*dep[l]-dep[a],-,rt2[l]);
}
dfs(,);
for(i=;i<=n;i++) printf("%d ",ans[i]);
return ;
}

别人的做法(大概写一下):

先把每个点x答案换一下形式:"以x为根的子树中有多少个起点/终点满足对应条件"

dfs(x)时,先dfs(所有子节点),然后统计自身答案,然后把自身点满足的性质(比如,是起点,是终点,是某一对起点与终点的lca,是某一对起点与终点的lca的父亲)(可以预处理出来)产生的贡献加进一个全局的贡献数组里面

洛谷 P1600 天天爱跑步的更多相关文章

  1. 洛谷P1600 天天爱跑步(线段树合并)

    小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn ...

  2. 洛谷P1600 天天爱跑步——树上差分

    题目:https://www.luogu.org/problemnew/show/P1600 看博客:https://blog.csdn.net/clove_unique/article/detail ...

  3. 洛谷P1600 天天爱跑步

    天天放毒... 首先介绍一个树上差分. 每次进入的时候记录贡献,跟出来的时候的差值就是子树贡献. 然后就可以做了. 发现考虑每个人的贡献有困难. 于是考虑每个观察员的答案. 把路径拆成两条,以lca分 ...

  4. 洛谷P1600 天天爱跑步(差分 LCA 桶)

    题意 题目链接 Sol 一步一步的来考虑 \(25 \%\):直接\(O(nm)\)的暴力 链的情况:维护两个差分数组,分别表示从左向右和从右向左的贡献, \(S_i = 1\):统计每个点的子树内有 ...

  5. 洛谷 P1600 天天爱跑步(LCA+乱搞)

    传送门 我们把每一条路径拆成$u->lca$和$lca->v$的路径 先考虑$u->lca$,如果这条路径会对路径上的某一个点产生贡献,那么满足$dep[u]-dep[x]=w[x] ...

  6. 洛谷P1600 天天爱跑步——题解

    题目传送 首先要考虑入手点.先考虑一个一个玩家处理,显然不加优化的话,时间复杂度是O(n)的.发现对于玩家路径上的点都有一个观察员,一个都不能忽视,看起来是很难优化了.在做题时,发现一个思路很难想,就 ...

  7. 洛谷$P1600$ 天天爱跑步 树上差分

    正解:树上差分 解题报告: 传送门$QwQ$! 这题还挺妙的,,,我想了半天才会$kk$ 首先对一条链$S-T$,考虑先将它拆成$S-LCA$和$LCA-T$,分别做.因为总体上来说差不多接下来我就只 ...

  8. [NOIP 2016D2T2/Luogu P1600] 天天爱跑步 (LCA+差分)

    待填坑 Code //Luogu P1600 天天爱跑步 //Apr,4th,2018 //树上差分+LCA #include<iostream> #include<cstdio&g ...

  9. AC日记——天天爱跑步 洛谷 P1600

    天天爱跑步 思路: 树上差分+分层动态线段树: (伏地膜,跪烂xxy) 代码: #include <bits/stdc++.h> using namespace std; #define ...

随机推荐

  1. Friefox清除旧的网页缓存

    Ctrl + F5 适用于调试网页编码时,不断以旧设置显示页面

  2. Hadoop-异常-Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/avro/io/DatumReader

    //maven org.apache.avr 下载不完全 ,去maven   If you are using maven to build your jar, you need to add the ...

  3. unity3d 摄像机抖动特效

    摄像机抖动特效 在须要的地方调用CameraShake.Shake()方法就能够  

  4. 解决UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 12: ordinal not in range(128)的编码问题

    当我在运行一个基于scrapy的爬虫时出现UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 12: ordina ...

  5. linux系列之-—01 shell编程笔记

    一.特殊变量($0.$1.$2. $?. $# .$@. $*) shell编程中有一些特殊的变量可以使用.这些变量在脚本中可以作为全局变量来使用. 名称 说明 $0 脚本名称 $1-9 脚本执行时的 ...

  6. 最齐全的站点元数据meta标签的含义和使用方法

    最齐全的站点元数据meta标签的含义和使用方法 随着HTML5的流行和Web技术的不断演变,Meta标签队伍也越来越壮大,从Windows XP的IE6到现在Windows 7.Windows 8的I ...

  7. Nginx——静态资源服务器(一)

    java web的项目中,我们经常将项目部署到Tomcat或者jetty上,可以通过Tomcat或者jetty启动的服务来访问静态资源.但是随着Nginx的普及,用Nginx来作为静态资源服务器,似乎 ...

  8. 解决Linux环境Oracle显示乱码

    首先查看当前的编码格式 select userenv('language') from dual; 解决方法:   一.临时解决方法   切换到Oracle用户,执行   export NLS_LAN ...

  9. Delphi XE10调用WebService服务获取图片验证码

    最近做了一个程序,需要使用图片验证码,百度一下,网上一大把免费的WebService服务,随意找一个用用,效果还可以.WebService地址:http://www.webxml.com.cn/Web ...

  10. 线程之间的通信socketpair【学习笔记】【原创】

    平台信息:内核:linux3.1.0系统:android5.0平台:tiny4412 作者:庄泽彬(欢迎转载,请注明作者) 说明: 韦老师的安卓视频学习笔记 一.在一个进程中多个线程如何进行通信,主要 ...