KokiNiwa @ 2019-05-31 21:53:23
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int N = 3e5, Big = 6e5 + 10; //一共有3e5个点
struct Node
{
int v, nxt;
} edge[N<<1];
int head[N], tot;
void addedge(int u, int v)
{
edge[++tot].v = v;
edge[tot].nxt = head[u];
head[u] = tot;
}
int n, m, w[N], s[N], t[N], lca[N], Snum[N]; //w[i]表示编号为i的点的观测时间
void input()
{
scanf("%d %d", &n, &m);
for (int i = 1; i < n; ++i)
{
int u, v;
scanf("%d %d", &u, &v);
addedge(u, v);
addedge(v, u);
}
for (int i = 1; i <= n; ++i)
scanf("%d", &w[i]);
for (int i = 1; i <= m; ++i)
{
scanf("%d %d", &s[i], &t[i]);
++Snum[s[i]];
}
}
int fa[N][20], level[N]; //编号为i的点的父亲为fa[i][0]
//fa[i][j]是节点i的2^j次方祖先
void prepare(int u, int from) //u是从v过来的
{
level[u] = level[from] + 1;
fa[u][0] = from;
for (int i = 1; i <= 18; ++i)
fa[u][i] = fa[fa[u][i-1]][i-1];
for (int i = head[u]; i; i = edge[i].nxt)
{
int v = edge[i].v;
if (v != from)
prepare(v, u);
}
}
void swap(int &u, int &v)
{
int tmp = u;
u = v;
v = tmp;
}
int LCA(int u, int v) //倍增LCA
{
if (level[u] < level[v])
swap(u, v);
for (int i = 18; i >= 0; --i)
if (level[fa[u][i]] >= level[v])
u = fa[u][i];
if (u == v)
return u;
for (int i = 18; i >= 0; --i)
if (fa[u][i] != fa[v][i])
u = fa[u][i], v = fa[v][i];
return fa[u][0];
}
vector<int> putOff[N]; //在一个结点i是LCA的时候,要去掉s[putOff[i]]里面所有数在桶里面的deep值
vector<int> uToL[N]; //从七点映射到lca
vector<int> vToS[N];
void useLCA()
{
for (int i = 1; i <= m; ++i)
{
lca[i] = LCA(s[i], t[i]);
putOff[lca[i]].push_back(s[i]);
uToL[s[i]].push_back(lca[i]); //忘了初始化这个变量了
vToS[t[i]].push_back(2 * level[lca[i]] - level[s[i]]);
}
}
int bucket[Big];
inline void addbucket(int val, int x) //在哈希表里面加入一个值
{
bucket[val+n] += x;
}
inline int askbucket(int val)
{
if (val + n < 0)
return 0;
return bucket[val+n];
}
int ans[N];
void dfs1(int u)
{
int origin = askbucket(w[u] + level[u]);
for (int i = head[u]; i; i = edge[i].nxt)
{
int v = edge[i].v;
if (v != fa[u][0])
dfs1(v);
}
addbucket(level[u], Snum[u]);
ans[u] += askbucket(w[u] + level[u]) - origin;
int sze = putOff[u].size();
for (int i = 0; i < sze; ++i)
addbucket(level[putOff[u][i]], -1);
}
void cleanbucket()
{
memset(bucket, 0, sizeof(bucket));
}
void dfs2(int u)
{
int origin = askbucket(level[u] - w[u]);
for (int i = head[u]; i; i = edge[i].nxt)
{
int v = edge[i].v;
if (v != fa[u][0])
dfs2(v); //这个函数我直接复制的dfs1,这里忘了改成dfs2()了
}
int sze = vToS[u].size();
for (int i = 0; i < sze; ++i) //由于只考虑某个节点的子树对某个点的贡献,所以我们要把这个循环放在上一个循环的后面
addbucket(vToS[u][i], 1);
ans[u] += askbucket(level[u] - w[u]) - origin; //刚才我这里写成了w[u] - level[u],时时刻刻想着算式的意义
sze = putOff[u].size();
for (int i = 0; i < sze; ++i)
addbucket(2 * level[u] - level[putOff[u][i]], -1);
}
void remove()
{
for (int i = 1; i <= m; ++i)
if (level[lca[i]] - level[s[i]] == w[lca[i]])
--ans[lca[i]];
}
void output()
{
for (int i = 1; i <= n; ++i)
printf("%d ", ans[i]);
printf("\n");
}
int main()
{
input();
prepare(1, 0);
useLCA();
dfs1(1);
cleanbucket();
dfs2(1);
remove();
output();
return 0;
}
#1
AC
51ms/24248KB
#2
AC
194ms/42588KB
#3
AC
187ms/42632KB
#4
AC
198ms/42584KB
#5
AC
213ms/42980KB
#6
WA
#7
AC
186ms/42956KB
#8
WA
#9
WA
#10
WA
#11
WA
#12
AC
55ms/24288KB
#13
WA
#14
AC
53ms/24436KB
#15
AC
51ms/24476KB
#16
AC
54ms/24324KB
#17
AC
373ms/49288KB
#18
AC
318ms/49340KB
#19
WA
#20
AC
201ms/42492KB
情况大概就是这样。 有哪一位大佬能帮我调一下嘛?
by Seauy @ 2020-07-02 23:14:04
列队还行吧……保卫王国好像是有些变态
然鹅这一年TG无数人AK是几个意思