@atcoder - ABC133F@ Colorful Tree
Posted tiw-air-oao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@atcoder - ABC133F@ Colorful Tree相关的知识,希望对你有一定的参考价值。
@[email protected]
题面明天起来补。。。
@[email protected]
跟颜色有关,虽然题目中说是要“修改”实际上每一个询问之间是独立的,即修改不会有时效性。
所以不难想到可以使用树上莫队。
首先将边的颜色与边权下放至点。然后莫队时,统计出区间内每个点的点权(就是下放的边权)和 S、区间每种颜色的出现次数 cnt[i]、区间每种颜色的边权和 s[i]
查询时答案即为 S - s[x] + y*cnt[x]。
有关树上莫队的实现方法,你可以在yhn学长的这篇博客里找到详情。
@accepted [email protected]
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100000;
const int BLOCK = 320;
struct edge
int to, dis, clr;
edge *nxt;
edges[2*MAXN + 5], *adj[MAXN + 5], *ecnt = &edges[0];
void addedge(int u, int v, int c, int d)
edge *p = (++ecnt);
p->to = v, p->clr = c, p->dis = d;
p->nxt = adj[u], adj[u] = p;
p = (++ecnt);
p->to = u, p->clr = c, p->dis = d;
p->nxt = adj[v], adj[v] = p;
int clr[MAXN + 5], dis[MAXN + 5];
int fa[MAXN + 5][20], dep[MAXN + 5];
int dfn[2*MAXN + 5], fir[MAXN + 5], bac[MAXN + 5], dcnt = 0;
void dfs(int x, int pre)
dfn[++dcnt] = x, fir[x] = dcnt;
fa[x][0] = pre, dep[x] = dep[pre] + 1;
for(int i=1;i<20;i++)
fa[x][i] = fa[fa[x][i-1]][i-1];
for(edge *p=adj[x];p;p=p->nxt)
if( p->to != pre )
dfs(p->to, x);
clr[p->to] = p->clr, dis[p->to] = p->dis;
dfn[++dcnt] = x, bac[x] = dcnt;
int lca(int u, int v)
if( dep[u] < dep[v] ) swap(u, v);
for(int i=19;i>=0;i--)
if( dep[fa[u][i]] >= dep[v] )
u = fa[u][i];
if( u == v ) return u;
for(int i=19;i>=0;i--)
if( fa[u][i] != fa[v][i] )
u = fa[u][i], v = fa[v][i];
return fa[u][0];
struct query
int le, ri, num;
int x, y;
qry[MAXN + 5];
bool operator < (query a, query b)
return (a.le/BLOCK == b.le/BLOCK) ? a.ri < b.ri : a.le < b.le;
int nwres, cnt[MAXN + 5], tag[MAXN + 5];
int sum[MAXN + 5], ans[MAXN + 5];
void update(int x)
int y = dfn[x];
if( tag[y] )
cnt[clr[y]]--, sum[clr[y]] -= dis[y], nwres -= dis[y];
else cnt[clr[y]]++, sum[clr[y]] += dis[y], nwres += dis[y];
tag[y] ^= 1;
int main()
int N, Q; scanf("%d%d", &N, &Q);
for(int i=1;i<N;i++)
int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d);
addedge(a, b, c, d);
dfs(1, 0);
for(int i=1;i<=Q;i++)
int x, y, u, v; scanf("%d%d%d%d", &x, &y, &u, &v);
int l = lca(u, v);
if( l == u || l == v )
if( l == v ) swap(u, v);
qry[i].le = fir[u] + 1, qry[i].ri = fir[v];
else
if( fir[u] > fir[v] ) swap(u, v);
qry[i].le = bac[u], qry[i].ri = fir[v];
qry[i].num = i, qry[i].x = x, qry[i].y = y;
sort(qry + 1, qry + Q + 1);
int l = 1, r = 0;
for(int i=1;i<=Q;i++)
while( l > qry[i].le ) update(--l);
while( r < qry[i].ri ) update(++r);
while( l < qry[i].le ) update(l++);
while( r > qry[i].ri ) update(r--);
ans[qry[i].num] = nwres - sum[qry[i].x] + cnt[qry[i].x]*qry[i].y;
for(int i=1;i<=Q;i++)
printf("%d\n", ans[i]);
@[email protected]
他们在说这道题很难。。。
我觉得是因为他们没学过莫队的原因吧。。。
以上是关于@atcoder - ABC133F@ Colorful Tree的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 133 F - Colorful Tree
AtCoder ABC 127F Absolute Minima