一个很玄学的问题
查看原帖
一个很玄学的问题
544756
xiaobing楼主2024/10/25 21:39
//#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lll __int128
#define ull unsigned long long
#define ui unsigned int
#define veci vector<int>
#define vecb vector<bool>
#define vecl vector<long long>
#define vecn vector<node>
#define vece vector<edge>
#define quei queue<int>
#define quen queue<node>
const int N = 1e6 + 10, inf = 0x7FFFFFFF;
const ll INF = 0x7FFFFFFFFFFFFFFF;
ll mod;
struct tree {
	struct node {
		long long v, tag;
		int ls, rs;
	};
	int tot, root, n;
	vector<node> tr;
	void build(int& x, int l, int r) {
		if (!x)x = ++tot, tr.push_back({ 0,0,0,0 });
		if (l == r)return;
		int mid = (l + r) >> 1;
		build(tr[x].ls, l, mid);
		build(tr[x].rs, mid + 1, r);
		return;
	}
	void init(int nn) {
		tr.reserve(1000000);
		tr.resize(1);
		n = nn;
		tot = 0;
		root = 0;
		build(root, 1, n);
		return;
	}
	tree(int nn = 0) { init(nn); }
	void addtag(int x, int l, int r, long long k) {
		tr[x].tag += k; tr[x].tag %= mod;
		tr[x].v += k * (r - l + 1);
		tr[x].v %= mod;
		return;
	}
	void push_down(int x, int l, int r) {
		if (!tr[x].tag)return;
		int mid = (l + r) >> 1;
		addtag(tr[x].ls, l, mid, tr[x].tag);
		addtag(tr[x].rs, mid + 1, r, tr[x].tag);
		tr[x].tag = 0;
		return;
	}
	void push_up(int x) {
		tr[x].v = tr[tr[x].ls].v + tr[tr[x].rs].v;
		tr[x].v %= mod;
		return;
	}
	void updata(int x, int l, int r, int L, int R, long long k) {
		push_down(x, l, r);
		if (L <= l && r <= R) {
			addtag(x, l, r, k);
			return;
		}
		int mid = (l + r) >> 1;
		if (mid >= L)updata(tr[x].ls, l, mid, L, R, k);
		if (mid < R)updata(tr[x].rs, mid + 1, r, L, R, k);
		push_up(x);
		return;
	}
	long long query(int x, int l, int r, int L, int R) {
		push_down(x, l, r);
		if (L <= l && r <= R)
			return tr[x].v;
		int mid = (l + r) >> 1;
		long long res = 0;
		if (mid >= L)res += query(tr[x].ls, l, mid, L, R);
		if (mid < R)res += query(tr[x].rs, mid + 1, r, L, R);
		return res;
	}
};
struct ctree {
	struct node {
		int sz, fa, top, depth, son, dfn;
	};
	struct edge {
		int to, nxt;
	};
	int cnt, root, tot, n;
	tree tr;
	vece e;
	vecn p;
	veci head;
	void init(int nn, int rt) {
		int n = nn;
		p.resize(n + 1);
		head.resize(n + 1);
		e.reserve(1000000);
		e.resize(2); cnt = 1;
		tot = 0; root = rt;
		p[root].depth = 1;
		p[root].top = root;
		tr.init(n);
	}
	ctree(int nn = 0, int rt = 1) { init(nn, rt); }
	void insert(int u, int v) {
		e.push_back({ v,head[u] });
		head[u] = ++cnt;
		e.push_back({ u,head[v] });
		head[v] = ++cnt;
		return;
	}
	void pre(int x) {
		p[x].sz = 1;
		if (!head[x])return;
		for (int i = head[x]; i; i = e[i].nxt) {
			int to = e[i].to; 
			if (to == p[x].fa)continue;
			p[to].fa = x; 
			p[to].depth = p[x].depth + 1;
			pre(to);
			p[x].sz += p[to].sz;
			if (!p[x].son || p[to].sz > p[p[x].son].sz)p[x].son = to;
		}
		return;
	}
	void get_dfn(int x) {
		p[x].dfn = ++tot;
		if (!head[x])return;
		get_dfn(p[x].son);
		for (int i = head[x]; i; i = e[i].nxt) {
			int to = e[i].to;
			if (to == p[x].fa || to == p[x].son)continue;
			get_dfn(to);
		}
		return;
	}
	void get_top(int x) {
		if (!head[x])return;
		for (int i = head[x]; i; i = e[i].nxt) {
			int to = e[i].to;
			if (to == p[x].fa)continue;
			if (p[x].son == to)
				p[to].top = p[x].top;
			else p[to].top = to;
			get_top(to);
		}
		return;
	}
	int get_lca(int u, int v) {
		while (p[u].top != p[v].top) {
			if (p[p[u].top].depth < p[p[v].top].depth)
				swap(u, v);
			u = p[p[u].top].fa;
		}
		if (p[u].depth > p[v].depth)swap(u, v);
		return u;
	}
	void build(vecl a) {
		for (int i = 1; i <= n; i++) 
			tr.updata(tr.root, 1, n, i, i, a[i - 1]);
		return;
	}
	void updata1(int u, int v,ll k) {
		while (p[u].top != p[v].top) {
			if (p[p[u].top].depth < p[p[v].top].depth)
				swap(u, v);
			tr.updata(tr.root, 1, n, p[p[u].top].dfn, p[u].dfn, k);
			u = p[p[u].top].fa;
		}
		if (p[u].depth > p[v].depth)swap(u, v);
		tr.updata(tr.root, 1, n, p[u].dfn, p[v].dfn, k);
		return;
	}
	void updata2(int u, ll k) {
		tr.updata(tr.root, 1, n, p[u].dfn, p[u].dfn + p[u].sz - 1, k);
		return;
	}
	ll query1(int u, int v) {
		ll res = 0;
		while (p[u].top != p[v].top) {
			if (p[p[u].top].depth < p[p[v].top].depth)
				swap(u, v);
			res += tr.query(tr.root, 1, n, p[p[u].top].dfn, p[u].dfn);
			u = p[p[u].top].fa;
		}
		if (p[u].depth > p[v].depth)swap(u, v);
		res += tr.query(tr.root, 1, n, p[u].dfn, p[v].dfn);
		return res;
	}
	ll query2(int u) {
		return tr.query(tr.root, 1, n, p[u].dfn, p[u].dfn + p[u].sz - 1);
	}
};
int main() {
	//freopen("train.in", "r", stdin);
	//freopen("train.out", "w", stdout);
	//ios::sync_with_stdio(0);
	//cin.tie(0); cout.tie(0);
	int n, m, rt;
	cin >> n >> m >> rt >> mod;
	vecl a(n);
	for (int i = 0; i < n; i++)
		cin >> a[i]; 
	ctree tr(n, rt);
	for (int i = 1; i < n; i++) {
		int u, v; cin >> u >> v;
		tr.insert(u, v);
	}
	tr.pre(rt);
	tr.get_dfn(rt);
	tr.get_top(rt);
	tr.build(a);
	while (m--) {
		int opt, u, v, k;
		cin >> opt >> u;
		if (opt == 1) {
			cin >> v >> k;
			tr.updata1(u, v, k);
		}
		if (opt == 2) {
			cin >> v;
			cout << tr.query1(u, v) << '\n';
		}
		if (opt == 3) {
			cin >> k;
			tr.updata2(u, k);
		}
		if (opt == 4) {
			cout << tr.query2(u) << '\n';
		}
	}
	return 0;
}

为什么加了线段树以后一访问ctree就运行错误了,没加线段树的代码可以正常跑过LCA的

2024/10/25 21:39
加载中...