@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

题解 AtCoder abc154 F

Atcoder Beginner ABC166 F

[Atcoder ABC222] F - Expensive Expense | 妙用树的直径 | Dijkstra

Modulo Summation atcoder abc103