码迷,mamicode.com
首页 > 其他好文 > 详细

@atcoder - ABC133F@ Colorful Tree

时间:2019-07-07 23:55:59      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:tag   --   des   details   ==   class   opera   一个   出现   


@description@

题面明天起来补。。。

@solution@

跟颜色有关,虽然题目中说是要“修改”实际上每一个询问之间是独立的,即修改不会有时效性。
所以不难想到可以使用树上莫队。

首先将边的颜色与边权下放至点。然后莫队时,统计出区间内每个点的点权(就是下放的边权)和 S、区间每种颜色的出现次数 cnt[i]、区间每种颜色的边权和 s[i]
查询时答案即为 S - s[x] + y*cnt[x]。

有关树上莫队的实现方法,你可以在yhn学长的这篇博客里找到详情。

@accepted code@

#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]);
}

@details@

他们在说这道题很难。。。

我觉得是因为他们没学过莫队的原因吧。。。

@atcoder - ABC133F@ Colorful Tree

标签:tag   --   des   details   ==   class   opera   一个   出现   

原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/11148818.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!