题目链接:

luogu1600

谨以此题纪念那段年少无知但充满趣味的恬淡时光

附上一位dalao的博客链接:https://www.luogu.org/blog/user26242/ke-pa-di-tian-tian-ai-pao-bu

我写这道题的时候脑袋里一直想的是他还没AFO的时候的那段日子,真是快乐啊,虽然我那时什么都不会

好了废话结束

他写的是最为常见的差分+\(LCA\)+桶的写法,在此不再赘述

其实这是一道线段树合并的基础题

常规套路:我们将路径\((s,t)\)拆成\((s,lca)\)和\((lca,t)\),在这两段路径中

1)如果在\((s,lca)\)上的一点\(i\)看到,则\(w_i=dep_s-dep_i\),即\(w_i+dep_i=dep_s\)

2)如果在\((lca,t)\)上的一点\(i\)看到,则\(w_i=dep_s-dep_{lca}+dep_i-dep_{lca}\),即\(w_i-dep_i=dep_s-dep_{lca}*2\)

也就是说我们对于树上的某点\(i\),需要统计它的子树中满足上两个式子中某一个的点的个数

这个可以用权值线段树的合并维护

同时考虑到该路径不会对\(lca\)以上部分的答案产生影响,故考虑树上差分;具体的,在\(s\)和\(t\)处放上\(+1\)标记,而在\(fa_{lca}\)放上两个\(-1\)标记

代码注意事项

1)第二个式子中可能会出现负数,因此将值域整体向右平移\(n\)个单位

2)当这条路径的\(lca\)是一个可以被统计到答案的点时,它会被统计两次(带回发现它对两个式子均成立)。这可以在打\(tag\)时直接判断

代码如下(常数很大,luogu不吸氧\(5317ms\))

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x)&(-x)
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=a;i>=b;i--)
#define maxd 1000000007
typedef long long ll;
const int N=100000;
const double pi=acos(-1.0);
struct edgenode{
int to,nxt;
}sq[600200];
int n,m,all=0,head[300300],w[300300],dep[300300],fa[300300][20],ans[300300]; int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
} struct segment_tree{
struct node{
int cnt,lson,rson;
}seg[10000800];
int tot,root[300100]; void insert(int &id,int l,int r,int pos,int val)
{
if (!id) id=(++tot);seg[id].cnt+=val;
if (l==r) return;
int mid=(l+r)>>1;
if (pos<=mid) insert(seg[id].lson,l,mid,pos,val);
else insert(seg[id].rson,mid+1,r,pos,val);
} int merge(int x,int y,int l,int r)
{
if ((!x) || (!y)) return x+y;
seg[x].cnt+=seg[y].cnt;
int mid=(l+r)>>1;
seg[x].lson=merge(seg[x].lson,seg[y].lson,l,mid);
seg[x].rson=merge(seg[x].rson,seg[y].rson,mid+1,r);
return x;
} int query(int id,int l,int r,int pos)
{
if (l==r) return seg[id].cnt;
int mid=(l+r)>>1;
if (pos<=mid) return query(seg[id].lson,l,mid,pos);
else return query(seg[id].rson,mid+1,r,pos);
}
}seg1,seg2; void add(int u,int v)
{
all++;sq[all].to=v;sq[all].nxt=head[u];head[u]=all;
} int query_lca(int u,int v)
{
if (dep[u]<dep[v]) swap(u,v);
int tmp=dep[u]-dep[v];
rep(i,0,19)
if ((tmp>>i)&1) u=fa[u][i];
if (u==v) return u;
per(i,19,0)
if (fa[u][i]!=fa[v][i]) {u=fa[u][i];v=fa[v][i];}
return fa[u][0];
} void dfs1(int u,int fu)
{
dep[u]=dep[fu]+1;fa[u][0]=fu;
rep(i,1,19) fa[u][i]=fa[fa[u][i-1]][i-1];
int i;
for (i=head[u];i;i=sq[i].nxt)
{
int v=sq[i].to;
if (v==fu) continue;
dfs1(v,u);
}
} void dfs2(int u,int fu)
{
int i;
for (i=head[u];i;i=sq[i].nxt)
{
int v=sq[i].to;
if (v==fu) continue;
dfs2(v,u);
seg1.root[u]=seg1.merge(seg1.root[u],seg1.root[v],0,n);
seg2.root[u]=seg2.merge(seg2.root[u],seg2.root[v],0,n*2);
}
if ((w[u]+dep[u]>=0) && (w[u]+dep[u]<=n))
ans[u]+=seg1.query(seg1.root[u],0,n,w[u]+dep[u]);
if ((w[u]-dep[u]>=-n) && (w[u]-dep[u]<=n))
ans[u]+=seg2.query(seg2.root[u],0,2*n,w[u]-dep[u]+n);
} int main()
{
n=read();m=read();
seg1.tot=0;seg2.tot=0;
rep(i,1,n-1)
{
int u=read(),v=read();
add(u,v);add(v,u);
}
dfs1(1,0);
rep(i,1,n) w[i]=read();
rep(i,1,m)
{
int s=read(),t=read(),lca=query_lca(s,t),fal=fa[lca][0];
seg1.insert(seg1.root[s],0,n,dep[s],1);
seg1.insert(seg1.root[fal],0,n,dep[s],-1);
seg2.insert(seg2.root[t],0,n*2,dep[s]-2*dep[lca]+n,1);
seg2.insert(seg2.root[fal],0,n*2,dep[s]-2*dep[lca]+n,-1);
if (w[lca]+dep[lca]==dep[s]) ans[lca]--;
}
dfs2(1,0);
rep(i,1,n) printf("%d ",ans[i]);
return 0;
}

[luogu1600]NOIp2016D1T2 天天爱跑步的更多相关文章

  1. [luogu1600 noip2016] 天天爱跑步 (树上差分)

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

  2. luogu1600 [NOIp2016]天天爱跑步 (tarjanLca+dfs)

    经过部分分的提示,我们可以把一条路径切成s到lca 和lca到t的链 这样就分为向上的链和向下的链,我们分开考虑: 向上:如果某一个链i可以对点x产生贡献,那么有deep[x]+w[x]=deep[S ...

  3. 【神仙题】【P1600】【NOIP2016D1T2】天天爱跑步

    传送门 Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游 ...

  4. UOJ261 【NOIP2016】天天爱跑步

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  5. BZOJ4719 [Noip2016]天天爱跑步

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  6. noip2016天天爱跑步

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

  7. bzoj 4719: [Noip2016]天天爱跑步

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

  8. [NOIP]2016天天爱跑步

    [NOIP]2016天天爱跑步 标签: LCA 树上差分 NOIP Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是 ...

  9. NOIP2016 天天爱跑步 80分暴力

    https://www.luogu.org/problem/show?pid=1600 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养 ...

随机推荐

  1. 原子操作&普通锁&读写锁

    一:原子操作CAS(compare-and-swap) 原子操作分三步:读取addr的值,和old进行比较,如果相等,则将new赋值给*addr,他能保证这三步一起执行完成,叫原子操作也就是说它不能再 ...

  2. sql字符串分割扩展方法

    可编程性—表值函数 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE FUNCTION [dbo].[Split] ( @RowData ...

  3. WPF 水印TextBox WatermarkTextBox

    //https://blog.csdn.net/puchitomato/article/details/12248691 转自以上链接,自己添加了Enter响应事件.    public class ...

  4. 解决gitbook报错问题

    这个问题困扰了我 很久,网友给出了很多解决方案,我都亲测不靠谱. 以下解决方法亲测靠谱: OS:Win7 Gitbook版本: 3.2.3 Nodejs: V8.9.1 步骤: 1. 编辑文件 C:\ ...

  5. es6 generator函数

    es6 新增了Generator函数,一种异步编程的解决方案 回顾一下,es6 提供了新的遍历方法,for of ,适用于各种数据集合,统一了遍历操作,原生支持for of 集合的数据集合有.数组,字 ...

  6. iBatis第四章:动态SQL的用法

    一.什么是动态SQL,以及使用动态SQL的好处 所谓动态SQL,是针对静态SQL而言的,静态SQL的SQL语句是固定的,使用动态SQL是为了增强SQL的灵活性和复用性,可以用一个动态SQL达到在不同条 ...

  7. Python编写的Linux邮件发送工具

    之前有用过Linux自带的mail工具来定时发送邮件,但是要装mailx还有配mail.rc,这还比较正常,关键是到了ubantu下这工具用起来真是操蛋,如果哪天其他的unix like操作系统也有需 ...

  8. Microsoft Deployment Toolkit build 8456

    MDT build 8456的重大变化摘要. 支持的配置更新 Windows ADK for Windows 10,版本1809 Windows 10,版本1809 Configuration Man ...

  9. zabbix监控交换机状态

    1.在Zabbix中添加主机 输入名称.群组和交换机IP(交换机要开启snmp) 2.创建监控项 输入OID和其它信息(键值随便填,但是不能和系统内的键值重复)OID获取方法可查看上一篇文章:http ...

  10. 把ESXi中的虚拟机通过OVA/OVF导出的方式迁移到Proxmox 5

    引用地址:https://blog.csdn.net/zebra2011/article/details/83046841 一.前言    之前发现ESXi是免费的时候,非常兴奋地把几台服务器都装上了 ...