标签:tag -- des details == class opera 一个 出现
题面明天起来补。。。
跟颜色有关,虽然题目中说是要“修改”实际上每一个询问之间是独立的,即修改不会有时效性。
所以不难想到可以使用树上莫队。
首先将边的颜色与边权下放至点。然后莫队时,统计出区间内每个点的点权(就是下放的边权)和 S、区间每种颜色的出现次数 cnt[i]、区间每种颜色的边权和 s[i]
查询时答案即为 S - s[x] + y*cnt[x]。
有关树上莫队的实现方法,你可以在yhn学长的这篇博客里找到详情。
#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]);
}
他们在说这道题很难。。。
我觉得是因为他们没学过莫队的原因吧。。。
@atcoder - ABC133F@ Colorful Tree
标签:tag -- des details == class opera 一个 出现
原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/11148818.html