[luogu1600]NOIp2016D1T2 天天爱跑步
题目链接:
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 天天爱跑步的更多相关文章
- [luogu1600 noip2016] 天天爱跑步 (树上差分)
题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵 ...
- luogu1600 [NOIp2016]天天爱跑步 (tarjanLca+dfs)
经过部分分的提示,我们可以把一条路径切成s到lca 和lca到t的链 这样就分为向上的链和向下的链,我们分开考虑: 向上:如果某一个链i可以对点x产生贡献,那么有deep[x]+w[x]=deep[S ...
- 【神仙题】【P1600】【NOIP2016D1T2】天天爱跑步
传送门 Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游 ...
- UOJ261 【NOIP2016】天天爱跑步
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- BZOJ4719 [Noip2016]天天爱跑步
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- noip2016天天爱跑步
题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 个结点 ...
- bzoj 4719: [Noip2016]天天爱跑步
Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一 ...
- [NOIP]2016天天爱跑步
[NOIP]2016天天爱跑步 标签: LCA 树上差分 NOIP Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是 ...
- NOIP2016 天天爱跑步 80分暴力
https://www.luogu.org/problem/show?pid=1600 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养 ...
随机推荐
- &,^,|,的简化计算与理解
(全部和2进制有关 , 凡是2的次方数都是独立数列,都要先分解再计算的,该计算方式仅供手工计算理解,电脑会自动进行换算的) (第二个等号后面为2进制的结果,不够位在前面补0,1为真,0为假) A^ ...
- Innosetup 设置文件的相对路径
在使用innosetup自动化打包的过程中,如果打包配置文件要随代码一起提交,则需要将打包文件改为相对路径,以便在其它端也可以直接打包,而不需要再次修改文件路径参数. 添加自动化打包文件 1. 添加b ...
- ASP.NET WebApi系列
ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务. ASP.NET Web API 是一种用于在 .NET Framework 上构 ...
- Admin Console 反应慢的相关bug
一个常见问题是在 Admin console 刷新 server 列表时,页面反应慢.从 Admin Server 的 Thread Dump 可以看到 Admin server 到 Managed ...
- (三) Keras Mnist分类程序以及改用交叉熵对比
视频学习来源 https://www.bilibili.com/video/av40787141?from=search&seid=17003307842787199553 笔记 Mnist分 ...
- vue的组件化运用(数据在两个组件互传,小问题总结)
一.vue的组件化应用 首先,知道有哪些相关的属性需要用到,再慢慢去理解,运用. 1.两个vue页面 2. slot占位符(可用可不用) 3.props内置属性 4.watch监听函数 5.impor ...
- mysql的严格模式与无效字符编码问题
问题一般格式为: 1366 Incorrect string value: '' for column 1300 Invalid utf8 character string: '' 向mysql插入中 ...
- cvc-elt.1: Cannot find the declaration of element 'beans'Failed to read schema document 'http://www.springframework.org/schema/beans/spring- beans-3.0.xsd'
Multiple annotations found at this line: - cvc-elt.1: Cannot find the declaration of element 'beans' ...
- Win7环境 搭建IIS环境。发布asp.net MVC项目到IIS(第二期)
在IIS环境中给发布项目修改域名,192.168.1.1:8081 ---->> www.preject.com 一.在网站主页中,1找到绑定网站.2编辑. 二.修改网站配置参数. 三. ...
- 关于SQL Server 数据库归档的一些思考和改进
一.需求背景 SQL Server开源的归档工具不多,DBA一般都是通过计划任务来触发执行,执行的脚本多是SP或者是SSIS包.SSIS包的性能稍好一些,但是维护更新成本高些.所以更常见的是通过SP脚 ...