传送门

1A此题暴祭

(下面记点\(x\)深度为\(de_x\),某个时间点记为\(w_x\))

首先,每条路径是可以拆成往上和往下两条路径的

对于往上的路径,假设有个人往上跑,\(w_y\)在点\(y\),那么如果能对点\(x\)的观察员产生贡献,当且仅当\(w_x+de_x=w_y+de_y\)

对于往下的路径,假设有个人往下跑,\(w_y\)在点\(y\),那么如果能对点\(x\)的观察员产生贡献,当且仅当\(w_x-de_x=w_y-de_y\)

所以对于每个点开两个线段树,每个下表存\(w_x+de_x\)或\(w_x-de_x\)的点的个数,对于每条路径(x,y),记\(len\)为路径长度(结束时间点),\(mid\)为到达\(lca\)的时间,在\(x\)的第一个线段树的\(de_x\)处+1,在\(lca\)的第一个线段树的\(mid+de_{lca}\)处-1,在y的第二个线段树的\(len-de_y+n\)处+1,在\(fa_{lca}\)的第二个线段树的\(mid-1-de_{fa_{lca}}+n\)处-1(不能出现负下标).dfs整棵树,把\(x\)所有儿子的线段树并起来,然后这个点的答案就是第一棵线段树的\(w_x+de_x\)加第二棵线段树的\(w_x-de_x+n\)的值

我太傻了,这两颗线段树可以分开处理的,我放在一起处理了,空间爆炸,bzoj就过不去了qwq

#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double
#define eps (1e-5) using namespace std;
const int N=300000+10;
il LL rd()
{
LL x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int to[N<<1],nt[N<<1],hd[N],tot=1;
il void add(int x,int y)
{
++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
int n,m,w[N],an[N],fa[N],sz[N],de[N],son[N],top[N];
void dfs1(int x)
{
sz[x]=1;
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==fa[x]) continue;
fa[y]=x,de[y]=de[x]+1,dfs1(y),sz[x]+=sz[y];
if(sz[son[x]]<sz[y]) son[x]=y;
}
}
void dfs2(int x,int ntp)
{
top[x]=ntp;
if(son[x]) dfs2(son[x],ntp);
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
}
il int glca(int x,int y)
{
while(top[x]!=top[y])
{
if(de[top[x]]<de[top[y]]) swap(x,y);
x=fa[top[x]];
}
return de[x]<de[y]?x:y;
}
struct sgtree
{
int s[(N*3)*20],ch[(N*3)*20][2],rt[N],tt;
sgtree(){tt=0;}
il void inst(int o1,int o2,int x,int dt)
{
int l=1,r=n+n;
s[o1]=s[o2]+dt;
while(l<r)
{
int mid=(l+r)>>1;
if(x<=mid)
{
ch[o1][0]=++tt,ch[o1][1]=ch[o2][1];
o1=ch[o1][0],o2=ch[o2][0];
r=mid;
}
else
{
ch[o1][0]=ch[o2][0],ch[o1][1]=++tt;
o1=ch[o1][1],o2=ch[o2][1];
l=mid+1;
}
s[o1]=s[o2]+dt;
}
}
int merge(int o1,int o2)
{
if(!o1||!o2) return o1+o2;
int o=++tt;
s[o]=s[o1]+s[o2];
ch[o][0]=merge(ch[o1][0],ch[o2][0]);
ch[o][1]=merge(ch[o1][1],ch[o2][1]);
return o;
}
int quer(int o,int l,int r,int lx)
{
if(!o) return 0;
if(l==r) return s[o];
int mid=(l+r)>>1;
if(lx<=mid) return quer(ch[o][0],l,mid,lx);
else return quer(ch[o][1],mid+1,r,lx);
}
}S,T;
il void dfs3(int x)
{
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==fa[x]) continue;
dfs3(y),S.rt[x]=S.merge(S.rt[x],S.rt[y]),T.rt[x]=T.merge(T.rt[x],T.rt[y]);
}
an[x]=S.quer(S.rt[x],1,n+n,w[x]+de[x])+T.quer(T.rt[x],1,n+n,w[x]-de[x]+n);
} int main()
{
n=rd(),m=rd();
for(int i=1;i<n;i++) add(rd(),rd());
de[1]=1,dfs1(1),dfs2(1,1);
for(int i=1;i<=n;i++) w[i]=rd();
while(m--)
{
int x=rd(),y=rd(),lca=glca(x,y),lth=de[x]+de[y]-(de[lca]<<1),mid=lth-de[y]+de[lca],la;
la=S.rt[x],S.rt[x]=++S.tt,S.inst(S.rt[x],la,de[x],1);
la=S.rt[lca],S.rt[lca]=++S.tt,S.inst(S.rt[lca],la,de[lca]+mid,-1);
la=T.rt[y],T.rt[y]=++T.tt,T.inst(T.rt[y],la,lth-de[y]+n,1);
la=T.rt[fa[lca]],T.rt[fa[lca]]=++T.tt,T.inst(T.rt[fa[lca]],la,mid-1-de[fa[lca]]+n,-1);
}
dfs3(1);
for(int i=1;i<=n;i++) printf("%d ",an[i]);
return 0;
}

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

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

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

  2. [luogu]P1600 天天爱跑步[LCA]

    [luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上 ...

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

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

  4. P1600 天天爱跑步[桶+LCA+树上差分]

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

  5. Luogu:P1600 天天爱跑步

    来一发清新的80行 树剖 $LCA$ + 树上差分 题解. -----from Judge 本题题意大概是给出一棵 n 个节点的树以及 m 条有向路径, 并且每个点 i 都有一个权值 $w[i]$,如 ...

  6. 洛谷 P1600 天天爱跑步

    https://www.luogu.org/problemnew/show/P1600 (仅做记录) 自己的假方法: 每一次跑从a到b:设l=lca(a,b)对于以下产生贡献: a到l的链上所有的点( ...

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

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

  8. 洛谷P1600 天天爱跑步

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

  9. P1600 天天爱跑步

    lca真心不太会,这里只介绍60分做法,100的太难辣简单了就不介绍了 n<=1000 zz回溯爆搜 S[i]全部相等 这dfs序都不用lca的,2333,差分,然后输出判断一下是否是0(1到i ...

随机推荐

  1. 简单FTP服务器搭建

    1 配置IIS 打开控制面板-卸载程序-点击 打开或关闭windows功能-勾选 internet信息服务-确定 2 配置iis web站点 开始菜单-搜索iis并进入iis管理器(计算机-右键-管理 ...

  2. jquery为表格行添加上下移动画效果

    为项目列表项添加上下移动动画.首先想使用jquery animate来做到这一点.但我用的是table和tr作为列表和列表项,但jquery动画方法不支持table里的tr(Animations ar ...

  3. 一对一 只需将另一个表的id设置为主键和外键即可

    一对一 只需将另一个表的id设置为主键和外键即可 

  4. BZOJ4127Abs——树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

  5. websocket c++ example

    //============================================================================ // Name : websocket.c ...

  6. Luogu 1083 借教室(二分,差分)

    Luogu 1083 借教室(二分,差分) Description 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不 ...

  7. HDU 1074 Doing Homework (动态规划,位运算)

    HDU 1074 Doing Homework (动态规划,位运算) Description Ignatius has just come back school from the 30th ACM/ ...

  8. A1095. Cars on Campus

    Zhejiang University has 6 campuses and a lot of gates. From each gate we can collect the in/out time ...

  9. [codevs3342][绿色通道]

    codevs3342 思路: 既然是要求最小化最长空题段,直接二分答案.然后就是check函数的写法. 先考虑n方转移,假设当前二分的答案是x,用f[i]表示前i个题,第i道题写的最小花费时间.最后再 ...

  10. VUE在BODY上绑定enter事件

    mounted () { this.bodyListener = (e) => { if (e.keyCode === 13 && e.target === document.b ...