ABC133FColorful Tree

题意

给定一颗有颜色和权值的树,多次询问,每次询问,首先更改颜色为x的边的权值为y,然后输出u到v的距离。

数据都是1e5量级的。

思路

我自己一开始用树链剖分的做法。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = ; template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
} /**********showtime************/
const int maxn = 1e5+;
vector<int>mp[maxn];
vector<int>col[maxn];
vector<int>wen[maxn];
struct E{
int u, v, c, d;
void init(int U, int V, int C, int D) {
u = U;
v = V;
c = C;
d = D;
}
} edge[maxn];
int dp[maxn], son[maxn], sz[maxn], pa[maxn];
void dfs1(int u, int fa) {
sz[u] = ;
pa[u] = fa;
dp[u] = dp[fa] + ;
int mx = ;
for(int v : mp[u]) {
if(v == fa) continue;
dfs1(v, u);
sz[u] += sz[v];
if(mx < sz[v]) mx = sz[v], son[u] = v;
}
}
int id[maxn], top[maxn], tot;
void dfs2(int u, int fa, int tp) {
top[u] = tp;
id[u] = ++tot; if(son[u]) dfs2(son[u], u, tp); for(int v : mp[u]) {
if(v == fa || v == son[u]) continue;
dfs2(v, u, v);
}
} ll ans[maxn];
ll sum[maxn<<]; void update(int pos, int val, int le, int ri, int rt) {
if(le == ri) {
sum[rt] = val;
return;
}
int mid = (le + ri) >> ;
if(pos <= mid) update(pos, val, le, mid, rt<<);
else update(pos, val, mid+, ri, rt<<|);
sum[rt] = sum[rt<<] + sum[rt<<|];
}
ll query(int L, int R, int le, int ri, int rt) {
if(le >= L && ri <= R) {
return sum[rt];
}
ll res = ;
int mid = (le + ri) >> ;
if(mid >= L) res += query(L, R, le, mid, rt<<);
if(mid < R) res += query(L, R, mid+, ri, rt<<|);
return res;
}
int n,m;
ll solve(int u, int v) {
ll res = ;
while(top[u] != top[v]) {
if(dp[top[u]] > dp[top[v]]) {
res += query(id[top[u]] , id[u], , n, );
u = pa[top[u]];
}
else {
res += query(id[top[v]], id[v], , n, );
v = pa[top[v]];
}
}
if(u != v) {
if(id[u] < id[v]) res += query(id[u]+, id[v],, n, );
else res += query(id[v]+, id[u], , n, );
}
return res;
}
struct Q{
int x, y;
int u,v;
}q[maxn];
int main(){
scanf("%d%d", &n, &m);
for(int i=; i<n; i++) {
int u, v, c, d;
scanf("%d%d%d%d", &u, &v, &c, &d);
edge[i].init(u, v, c, d);
mp[u].pb(v);
mp[v].pb(u);
col[c].pb(i);
} dfs1(, );
dfs2(, , ); for(int i=; i<=m; i++) {
scanf("%d%d%d%d", &q[i].x, &q[i].y, &q[i].u, &q[i].v);
wen[q[i].x].pb(i);
}
for(int i=; i<=n; i++) {
if(wen[i].size() == || col[i].size() == ) continue;
/// count
for(int dd : col[i]) {
int u = edge[dd].u;
int v = edge[dd].v;
if(dp[u] < dp[v]) swap(u, v);
update(id[u], , , n, );
}
for(int dd: wen[i]) {
ans[dd] += solve(q[dd].u, q[dd].v) * q[dd].y;
}
for(int dd : col[i]) {
int u = edge[dd].u;
int v = edge[dd].v;
if(dp[u] < dp[v]) swap(u, v);
update(id[u], , , n, );
} ///sum
for(int dd : col[i]) {
int u = edge[dd].u;
int v = edge[dd].v;
if(dp[u] < dp[v]) swap(u, v);
update(id[u], edge[dd].d, , n, );
}
for(int dd: wen[i]) {
ans[dd] -= solve(q[dd].u, q[dd].v);
}
for(int dd : col[i]) {
int u = edge[dd].u;
int v = edge[dd].v;
if(dp[u] < dp[v]) swap(u, v);
update(id[u], , , n, );
}
} for(int i=; i<n; i++) {
int u = edge[i].u;
int v = edge[i].v;
if(dp[u] < dp[v]) swap(u, v);
update(id[u], edge[i].d, , n, );
}
for(int i=; i<=m; i++) {
int u = q[i].u;
int v = q[i].v;
ans[i] += solve(u, v);
}
for(int i=; i<=m; i++) printf("%lld\n", ans[i]);
return ;
}

还有树上莫队和树上差分的思路。

正在搞树上莫队的方法。搞好了。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = ; template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
} /**********showtime************/
const int maxn = 1e5+;
vector<int>mp[maxn];
struct E {
int u,v;
int c,d;
void init(int U, int V ,int C, int D) {
u = U; v = V; c = C; d = D;
}
} edge[maxn];
int dp[maxn];
int st[maxn ],ed[maxn], tim = ;
int fa[maxn][];
int a[maxn*];
void dfs(int u, int o) { dp[u] = dp[o] + ;
st[u] = ++tim;
a[tim] = u;
fa[u][] = o;
for(int i=; i<; i++)
fa[u][i] = fa[fa[u][i-]][i-];
for(int v : mp[u]) {
if(v == o) continue;
dfs(v, u);
}
ed[u] = ++tim;
a[tim] = u;
}
int lca(int u, int v) {
if(dp[u] < dp[v]) swap(u, v);
for(int i=; i>=; i--) {
if(dp[fa[u][i]] >= dp[v])
u = fa[u][i];
}
if(u == v) return u;
for(int i=; i>=; i--) {
if(fa[u][i] != fa[v][i])
u = fa[u][i], v = fa[v][i];
}
return fa[u][];
}
int c[maxn], d[maxn];
struct Q{
// int u, v;
int le, ri;
int lb;
int x, y;
int id;
} qry[maxn];
bool cmp(Q a, Q b) {
if(a.lb != b.lb)
return a.lb < b.lb;
return a.ri < b.ri;
}
int ans[maxn];
int sum,colcnt[maxn],colsum[maxn],pot[maxn];
void add(int id) { if(pot[a[id]] == ) pot[a[id]] = ;
else pot[a[id]] = ;
int col = c[a[id]];
if(pot[a[id]]) {
colcnt[col] ++;
colsum[col] += d[a[id]];
sum += d[a[id]];
}
else {
colcnt[col] --;
colsum[col] -= d[a[id]];
sum -= d[a[id]];
}
}
int main(){
int n,m;
scanf("%d%d", &n, &m);
int block = ;
for(int i=; i<n; i++) {
int u,v,c,d;
scanf("%d%d%d%d", &u, &v, &c, &d);
edge[i].init(u, v, c, d);
mp[u].pb(v);
mp[v].pb(u);
}
dfs(, );
for(int i=; i<n; i++) {
int u = edge[i].u, v = edge[i].v;
if(dp[u] < dp[v]) swap(u, v);
c[u] = edge[i].c;
d[u] = edge[i].d;
} for(int i=; i<=m; i++) {
int x, y, u, v;
scanf("%d%d%d%d", &x, &y, &u, &v);
qry[i].id = i;
qry[i].x = x;
qry[i].y = y;
if(st[u] > st[v]) swap(u, v);
int _lca = lca(u, v);
if(_lca == u) {
qry[i].le = st[u]+;
qry[i].ri = st[v];
qry[i].lb = qry[i].le / block;
}
else {
qry[i].le = ed[u];
qry[i].ri = st[v];
qry[i].lb = qry[i].le / block;
}
} sort(qry+, qry++m, cmp);
int le = , ri = ;
for(int i=; i<=m; i++) {
while(le < qry[i].le) add(le), le++;
while(le > qry[i].le) le--, add(le);
while(ri < qry[i].ri) ri++, add(ri);
while(ri > qry[i].ri) add(ri), ri--; ans[qry[i].id] = sum - colsum[qry[i].x] + colcnt[qry[i].x] * qry[i].y;
}
for(int i=; i<=m; i++) printf("%d\n", ans[i]);
return ;
}

ABC133F - Colorful Tree的更多相关文章

  1. @atcoder - ABC133F@ Colorful Tree

    目录 @description@ @solution - 1@ @accepted code - 1@ @solution - 2@ @accepted code - 2@ @details@ @de ...

  2. 2017 Multi-University Training Contest - Team 1 1003&&HDU 6035 Colorful Tree【树形dp】

    Colorful Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  3. hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

    /** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...

  4. AtCoder Beginner Contest 133 F Colorful Tree

    Colorful Tree 思路: 如果强制在线的化可以用树链剖分. 但这道题不强制在线,那么就可以将询问进行差分,最后dfs时再计算每个答案的修改值, 只要维护两个数组就可以了,分别表示根节点到当前 ...

  5. HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1

    /* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...

  6. [HDU6793] Tokitsukaze and Colorful Tree

    题目 又是一个条历新年,窗前的灼之花又盛开了. 时隔多年,现在只有这一棵树上盛开着残存的 \(n\) 朵灼之花了. 尽管如此,这些灼之 花仍散发出不同色彩的微弱的光芒. 灼之花的生命极为短暂,但它的花 ...

  7. Colorful tree

    cnbb 我被数组清零卡了一天.. 子树改色询问子树颜色数.. 先考虑颜色为x的节点对祖先答案的贡献,那么我们考虑把所有这些节点都搞出来,按dfs序排序,然后考虑每个节点a掌管的祖先是它和按dfs序的 ...

  8. 2017ACM暑期多校联合训练 - Team 1 1003 HDU 6035 Colorful Tree (dfs)

    题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...

  9. HDU-6035:Colorful Tree(虚树+DP)

    这里有三道长得像的题: 一:HDU6036: There is a tree with nn nodes, each of which has a type of color represented ...

随机推荐

  1. Samba:打造企业级授权文件共享服务器

    写在前面的话 先来说说故事背景:公司内部文件服务器的解决方案其实很多,对于中小型互联网公司,大多的在这一块的选型还是 FTP,或者 VSFTP,但是个人实在是对那个东西喜欢不起来,于是就选择了配置相对 ...

  2. Java学习-内存划分及内存的调用关系

    一.JAVA内存划分 JAVA的内存可以划分为五个部分:堆.栈.方法区.本地方法区和寄存器. 堆(Heap):凡是new出来的东西都在堆中 如: integer = new Integer(2) // ...

  3. 【Android】Failed to convert @drawable/picture into a drawable

    刚使用 eclipse 遇到了这个问题,图片的效果未显示出来,上网查找后发现这其实不算是问题:重启下工程或 eclipse 就行了. PS: 直接运行工程也可以,不影响效果.

  4. 【iOS】iOS viewDidLoad 方法名问题

    这两天在调试一个项目,跳转到一个页面的时候总是不显示标题栏(当然也没有标题栏的返回按钮),搞了好久,今天总算找到了问题:之前的开发人员竟然把 viewDidLoad 这个基本的方法名写成了 views ...

  5. Spring Boot @Condition 注解,组合条件你知道吗

    上一篇文章 你应该知道的 @ConfigurationProperties 注解的使用姿势,这一篇就够了 介绍了如何通过 @ConfigurationProperties 注解灵活读取配置属性,这篇文 ...

  6. 云计算网络基础笔记及VLAN交换机配置

  7. WebSocket的实现与应用

    WebSocket的实现与应用 前言 说到websocket,就不得不提http协议的连接特点特点与交互模型. 首先,http协议的特点是无状态连接.即http的前一次连接与后一次连接是相互独立的. ...

  8. Linux curl 命令详解

    命令概要 该命令设计用于在没有用户交互的情况下工作. curl 是一个工具,用于传输来自服务器或者到服务器的数据.「向服务器传输数据或者获取来自服务器的数据」 可支持的协议有(DICT.FILE.FT ...

  9. 世纪龙校招java开发一、二面 面经

    头一天做的笔试,涉及到计组基本知识,还有几道智力题.java部分很简单(真的很简单有点基础就划过了) 第二天收简历 在隔壁教室等 叫到你 你就去面试 一面:先自我介绍 1 == 和 equals区别( ...

  10. Salesforce LWC学习(四) 父子component交互 / component声明周期管理 / 事件处理

    我们在上篇介绍了 @track / @api的区别.在父子 component中,针对api类型的变量,如果声明以后就只允许在parent修改,son component修改便会导致报错. sonIt ...