LOJ146, LOJ147 DFS序

LOJ146:

给定一棵 n n n 个结点的树,根结点为 r r r,初始点权 w i w_i wi m m m 次操作:
1 , a , b , x 1, a, b, x 1,a,b,x a a a b b b 最短路径间点权都加上 x x x
2 , a 2, a 2,a,求结点 a a a 的点权;
3 , a 3, a 3,a,求结点 a a a 子树点权和。
( n , m ≤ 1 0 6 ) (n, m \leq 10^6) (n,m106)

链接:https://loj.ac/problem/146

LOJ147:

给定一棵 n n n 个结点的树,根结点为 r r r,初始点权 w i w_i wi m m m 次操作:
1 , a , x 1, a, x 1,a,x,将结点 a a a 点权加上 x x x
2 , a , x 2, a, x 2,a,x,将结点 a a a 子树点权都加上 x x x
3 , a , b 3, a, b 3,a,b,求 a a a b b b 最短路径间点权和。
( n , m ≤ 1 0 6 ) (n, m \leq 10^6) (n,m106)

链接:https://loj.ac/problem/147
 
先考虑第一道题,直接地可以用树链剖分做到 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n),但是这个复杂度是过不去的。只有修改有链操作,将 a b ab ab 路径的修改 + x +x +x,拆成 a r ar ar 路径 + x +x +x b r br br 路径 + x +x +x l c a ( a , b ) r lca(a, b)r lca(a,b)r 路径 − x -x x f a ( l c a ( a , b ) ) r fa(lca(a, b))r fa(lca(a,b))r 路径 − x -x x,子问题就是对 a r ar ar 路径上点权 + x +x +x

对点 a a a 加上 x x x,对询问点 b b b 有贡献,当且仅当 a a a b b b 子树内,那么对 a a a 单点修改 x x x,询问 b b b 则查询子树和(区间查询);

同理,对子树 a a a 加上 x x x,此操作对询问点 b b b 的贡献为 ( d e p a − d e p b + 1 ) ∗ x (dep_a - dep_b + 1) * x (depadepb+1)x,拆成两项 − d e p b ∗ x + ( 1 + d e p a ) ∗ x -dep_b * x + (1 + dep_a) * x depbx+(1+depa)x,前一项将 d e p b dep_b depb 提出,单独维护 x x x 的修改,后一项直接为 ( 1 + d e p a ) ∗ x (1 + dep_a) * x (1+depa)x 的修改,两个树状数组分别修改维护。

 
第二道题,只有询问有链操作,按第一道一样拆成 4 4 4 个到根的路径的查询。点 a a a 加上 x x x,仅当 b b b a a a 子树内时, a a a b b b 有贡献,那么将 a a a 子树打上标记 x x x(区间修改),差分一下变成两次单点修改, b b b 查询前缀和即是答案。

然后考虑 a a a 子树加上 x x x,同理, a a a b b b 的贡献为 ( d e p b − d e p a + 1 ) ∗ x (dep_b - dep_a + 1) * x (depbdepa+1)x,依然拆成 d e p b ∗ x + ( 1 − d e p a ) ∗ x dep_b * x + (1 - dep_a) * x depbx+(1depa)x,前一项提取 d e p b dep_b depb 后单独维护,后一项直接为 ( 1 − d e p a ) ∗ x (1 - dep_a) * x (1depa)x 的区间修改。

 
这两题卡常,需要快读,以及求 L C A LCA LCA 不能用倍增。
 

参考代码:

LOJ146:

#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e6 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

vector<int> G[maxn];
int a[maxn], dfn[maxn], dep[maxn], siz[maxn], top[maxn], fa[maxn], son[maxn];
int n, m, rt, tim;

struct BIT{

	ll c[maxn];
	#define lowb(x) ((x)&(-x))
	void update(int x, ll val){

		if(x <= 0) return;
		while(x <= n) c[x] += val, x += lowb(x);
	}
	ll query(int x){

		ll ret = 0;
		while(x) ret += c[x], x -= lowb(x);
		return ret;
	}
} c1, c2;

void dfs1(int u, int f){

	fa[u] = f, dep[u] = dep[f] + 1, siz[u] = 1, son[u] = 0;
	for(auto &v : G[u]){

		if(v == f) continue;
		dfs1(v, u);
		siz[u] += siz[v];
		if(siz[v] > siz[son[u]]) son[u] = v;
	}
}

void dfs2(int u, int t){

	dfn[u] = ++tim, top[u] = t;
	if(!son[u]) return;
	dfs2(son[u], t);
	for(auto &v : G[u]){

		if(v == fa[u] || v == son[u]) continue;
		dfs2(v, v);
	}
}

int lca(int u, int v){

	while(top[u] != top[v]){

		dep[top[u]] > dep[top[v]] ? u = fa[top[u]] : v = fa[top[v]];
	}
	return dep[u] < dep[v] ? u : v;
}

const int maxs = 1e3 + 5;
char buf[maxs], *p1 = buf, *p2 = buf;
inline char fr(){

	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, maxs, stdin)) == p1 ? -1 : *p1++;
}
#define gc fr()
inline void read(int &x){

	char ch; int flg = 0; while(!isdigit(ch = gc)) flg = ch == '-' ? 1 : flg;
	x = ch ^ 48; while(isdigit(ch = gc)) x = x * 10 + (ch ^ 48); x = flg ? -x : x; 
}

void update(int u, int v, ll val){

	int lc = lca(u, v), flc = fa[lc];
	c1.update(dfn[u], val);
	c1.update(dfn[v], val);
	c1.update(dfn[lc], -val);
	c1.update(dfn[flc], -val);
	c2.update(dfn[u], val * (dep[u] + 1));
	c2.update(dfn[v], val * (dep[v] + 1));
	c2.update(dfn[lc], -val * (dep[lc] + 1));
	c2.update(dfn[flc], -val * (dep[flc] + 1));
}

int main(){

	ios::sync_with_stdio(0); cin.tie(0);
	read(n), read(m), read(rt);
	for(int i = 1; i <= n; ++i){

		read(a[i]);
	}
	for(int i = 1; i < n; ++i){

		int u, v; read(u), read(v);
		G[u].pb(v), G[v].pb(u);
	}
	dfs1(rt, 0);
	dfs2(rt, rt);
	for(int i = 1; i <= n; ++i){

		update(i, i, a[i]);
	}
	while(m--){

		int opt, x, y, z; read(opt), read(x);
		if(opt == 1){

			read(y), read(z);
			update(x, y, z);
		}
		else if(opt == 2){
			
			ll ret = c1.query(dfn[x] + siz[x] - 1);
			ret -= c1.query(dfn[x] - 1);
			printf("%lld\n", ret);
		}
		else{

			ll ret = c2.query(dfn[x] + siz[x] - 1) - c2.query(dfn[x] - 1);
			ret -= dep[x] * (c1.query(dfn[x] + siz[x] - 1) - c1.query(dfn[x] - 1));
			printf("%lld\n", ret);
		}
	}
	return 0;
}

 
LOJ147:

#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e6 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

vector<int> G[maxn];
int a[maxn], dfn[maxn], siz[maxn], dep[maxn], fa[maxn], top[maxn], son[maxn];
int n, m, rt, tim;

struct BIT{

	ll c[maxn];
	#define lowb(x) ((x)&(-x))
	void update(int x, ll val){

		if(x <= 0) return;
		while(x <= n) c[x] += val, x += lowb(x);
	}
	ll query(int x){

		ll ret = 0;
		while(x) ret += c[x], x -= lowb(x);
		return ret;
	}
} c1, c2;

void dfs1(int u, int f){

	fa[u] = f, dep[u] = dep[f] + 1, siz[u] = 1, son[u] = 0;
	for(auto &v : G[u]){

		if(v == f) continue;
		dfs1(v, u);
		siz[u] += siz[v];
		son[u] = siz[v] > siz[son[u]] ? v : son[u];
	}
}

void dfs2(int u, int t){

	dfn[u] = ++tim, top[u] = t;
	if(!son[u]) return;
	dfs2(son[u], t);
	for(auto &v : G[u]){

		if(v == fa[u] || v == son[u]) continue;
		dfs2(v, v);
	}
}

int lca(int u, int v){

	while(top[u] != top[v]){

		dep[top[u]] > dep[top[v]] ? u = fa[top[u]] : v = fa[top[v]];
	}
	return dep[u] < dep[v] ? u : v;
}

ll query(int u, int v){

	int lc = lca(u, v), flc = fa[lc];
	ll ret = 0;
	ret += c1.query(dfn[u]) + c1.query(dfn[v]);
	ret -= c1.query(dfn[lc]) + c1.query(dfn[flc]);
	ret += dep[u] * c2.query(dfn[u]) + dep[v] * c2.query(dfn[v]);
	ret -= dep[lc] * c2.query(dfn[lc]) + dep[flc] * c2.query(dfn[flc]);
	return ret;
}

const int maxs = 1e3 + 5;
char buf[maxs], *p1 = buf, *p2 = buf;
inline char fr(){

	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, maxs, stdin)) == p1 ? -1 : *p1++;
}
#define gc fr()
inline void read(int &x){

	char ch; int flg = 0; while(!isdigit(ch = gc)) flg = ch == '-' ? 1 : flg;
	x = ch ^ 48; while(isdigit(ch = gc)) x = x * 10 + (ch ^ 48); x = flg ? -x : x; 
}

int main(){

	ios::sync_with_stdio(0); cin.tie(0);
	read(n), read(m), read(rt);
	for(int i = 1; i <= n; ++i){

		read(a[i]);
	}
	for(int i = 1; i < n; ++i){

		int u, v; read(u), read(v);
		G[u].pb(v), G[v].pb(u);
	}
	dfs1(rt, 0);
	dfs2(rt, rt);
	for(int i = 1; i <= n; ++i){

		c1.update(dfn[i], a[i]);
		c1.update(dfn[i] + siz[i], -a[i]);
	}
	while(m--){

		int opt, x, y; read(opt), read(x), read(y);
		if(opt == 1){

			c1.update(dfn[x], y);
			c1.update(dfn[x] + siz[x], -y);
		}
		else if(opt == 2){

			c1.update(dfn[x], y * 1ll * (1 - dep[x]));
			c1.update(dfn[x] + siz[x], -y * 1ll * (1 - dep[x]));
			c2.update(dfn[x], y);
			c2.update(dfn[x] + siz[x], -y);
		}
		else{

			ll ret = query(x, y);
			printf("%lld\n", ret);
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值