点8、9、10TLE求调
查看原帖
点8、9、10TLE求调
454980
Wugic_code楼主2024/3/29 22:54

萌新第一次学树剖……求大佬们指点,谢谢力!

其余点均>=5ms顺利通过

#include <iostream>
#include <cstring>

using namespace std;

//const int MAXN = 50;
const int MAXN = 100010;

long long cnter;

inline int LS(int x) {
	return x << 1;
}

inline int RS(int x) {
	return ((x << 1) | 1);
}

inline int LEN(int l, int r) {
	return r - l + 1;
}

inline int MID(int l, int r) {
	return l + ((r - l) >> 1);
}

int n, m, r, p;
int wSorted[MAXN];

class SegTree {
	public:
		SegTree() {};
		SegTree(int l, int r, int raw[]) {
			memset(data, 0, sizeof(data));
			memset(lazy, 0, sizeof(lazy));
			Builder(l, r, 1, raw);
			length = LEN(l, r);
			size = length * 4;
		}

		void Print() {
			cout << "Data: ";
			for (int i = 1; i <= size; ++i)
				cout << data[i] << ' ';
			cout << '\n'
			     << "Lazy: ";
			for (int i = 1; i <= size; ++i)
				cout << lazy[i] << ' ';
			return;
		}

		void Update(int l, int r, int k) {
			Updater(l, r, k, 1, 1, length);
			return;
		}
		int Query(int l, int r) {
			return Querier(l, r, 1, 1, length);
		}

	private:
		int data[4 * MAXN], lazy[4 * MAXN];
		int size, length;

		void Builder(int l, int r, int nowp, int raw[]) {
			if (l == r) {
				data[nowp] = raw[l] % p;
				return;
			}
			int mid = MID(l, r);
			Builder(l, mid, LS(nowp), raw);
			Builder(mid + 1, r, RS(nowp), raw);
			data[nowp] = (data[LS(nowp)] + data[RS(nowp)]) % p;
			return;
		}
		inline void PushDown(int nowp, int nowl, int nowr) {
			if (lazy[nowp] != 0) {
				int mid = MID(nowl, nowr);
				lazy[LS(nowp)] += lazy[nowp];
				lazy[RS(nowp)] += lazy[nowp];
				lazy[LS(nowp)] %= p;
				lazy[RS(nowp)] %= p;
				data[LS(nowp)] += lazy[nowp] * LEN(nowl, mid) % p;
				data[RS(nowp)] += lazy[nowp] * LEN(mid + 1, nowr) % p;
				data[LS(nowp)] %= p;
				data[RS(nowp)] %= p;
				lazy[nowp] = 0;
			}
			return;
		}
		void Updater(int l, int r, int k, int nowp, int nowl, int nowr) {
			if (nowl > r || nowr < l)
				return;
			else if (nowl >= l && nowr <= r) {
				data[nowp] += (k * LEN(nowl, nowr)) % p;
				data[nowp] %= p;
				if (nowl != nowr)
					lazy[nowp] += k, lazy[nowp] %= p;
			} else {
				int mid = MID(nowl, nowr);
				PushDown(nowp, nowl, nowr);
				Updater(l, r, k, LS(nowp), nowl, mid);
				Updater(l, r, k, RS(nowp), mid + 1, nowr);
				data[nowp] = (data[LS(nowp)] + data[RS(nowp)]) % p;
			}
			return;
		}
		int Querier(int l, int r, int nowp, int nowl, int nowr) {
			if (nowl > r || nowr < l)
				return 0;
			else if (nowl >= l && nowr <= r)
				return data[nowp] % p;
			else {
				int mid = MID(nowl, nowr);
				PushDown(nowp, nowl, nowr);
				return (Querier(l, r, LS(nowp), nowl, mid) + Querier(l, r, RS(nowp), mid + 1, nowr)) % p;
			}
		}
};

struct Graph {
	int e[MAXN], nxt[MAXN], first[MAXN], cnt, tim;
	int pointw[MAXN], fa[MAXN], dep[MAXN], siz[MAXN], hson[MAXN], dfn[MAXN], top[MAXN];

	Graph() {
		memset(dep, 0, sizeof(dep));
		memset(hson, -1, sizeof(hson));
		memset(nxt, -1, sizeof(nxt));
		memset(first, -1, sizeof(first));
		cnt = 0;
		tim = 0;
	}
	void Insert(int u, int v) {
		cnt++;
		e[cnt] = v;
		nxt[cnt] = first[u];
		first[u] = cnt;
	}
	void dfs1(int nowp, int f);
	void dfs2(int nowp, int top);
	void CUpdate(int x, int y, int k);
	int CQuery(int x, int y);
};

SegTree *tr;
Graph *gr;

inline void TUpdate(SegTree *t, Graph *g, int pos, int k) {
	k %= p;
	t->Update(g->dfn[pos], g->dfn[pos] + g->siz[pos] - 1, k);
	return;
}

inline int TQuery(SegTree *t, Graph *g, int pos) {
	return t->Query(g->dfn[pos], g->dfn[pos] + g->siz[pos] - 1) % p;
}

inline void read(int &x) {
	x = 0;
	int w = 1, ch = getchar();
	while (!isdigit(ch) && ch != '-')ch = getchar();
	if (ch == '-')w = -1, ch = getchar();
	while (isdigit(ch))x = (x << 3) + (x << 1) + (ch^'0'), ch = getchar();
	x = x * w;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

#ifndef ONLINE_JUDGE
//	freopen("P3384.in", "r", stdin);
//	freopen("outer.out", "w", stdout);
#endif

	int tu, tv, opt, tx, ty, tz;
	gr = new Graph();

//	cin >> n >> m >> r >> p;
	read(n);
	read(m);
	read(r);
	read(p);
	for (int i = 1; i <= n; i++)
		read(gr->pointw[i]);
	for (int i = 1; i < n; i++) {
		read(tu);
		read(tv);
		gr->Insert(tu, tv);
		gr->Insert(tv, tu);
	}

	gr->dfs1(r, r);
	gr->dfs2(r, r);
	tr = new SegTree(1, n, wSorted);

	for (int i = 1; i <= m; i++) {
		read(opt);
		switch (opt) {
			case 1:
//				cin >> tx >> ty >> tz;
				read(tx);
				read(ty);
				read(tz);
				tz %= p;
				gr->CUpdate(tx, ty, tz);
				break;
			case 2:
				read(tx);
				read(ty);
				cout << gr->CQuery(tx, ty) << '\n';
				break;
			case 3:
				read(tx);
				read(ty);
				TUpdate(tr, gr, tx, ty);
				break;
			case 4:
				read(tx);
				cout << TQuery(tr, gr, tx) << '\n';
				break;
		}
	}
	return 0;
}

void Graph::dfs1(int nowp, int f) {
	fa[nowp] = f;
	dep[nowp] = dep[f] + 1;
	siz[nowp] = 1;
	int heavySonSize = 0;
	for (int i = first[nowp]; i != -1; i = nxt[i]) {
		int v = e[i];
		if (v == f)
			continue;
		dfs1(v, nowp);
		siz[nowp] += siz[v];
		if (siz[v] > heavySonSize) {
			hson[nowp] = v;
			heavySonSize = siz[v];
		}
	}
	return;
}

void Graph::dfs2(int nowp, int topa) {
	tim++;
	dfn[nowp] = tim;
	top[nowp] = topa;
	wSorted[tim] = pointw[nowp];
	if (hson[nowp] == -1)
		return;
	dfs2(hson[nowp], topa);
	for (int i = first[nowp]; i != -1; i = nxt[i]) {
		int v = e[i];
		if (v != fa[nowp] && v != hson[nowp])
			dfs2(v, v);
	}
	return;
}

void Graph::CUpdate(int x, int y, int k) {
	cnter++;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]])
			swap(x, y);
		tr->Update(dfn[top[x]], dfn[x], k);
		x = fa[top[x]];
	}
	if (dep[x] > dep[y])
		swap(x, y);
	tr->Update(dfn[x], dfn[y], k);
}

int Graph::CQuery(int x, int y) {
	int sum = 0;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]])
			swap(x, y);
		sum += tr->Query(dfn[top[x]], dfn[x]);
		sum %= p;
		x = fa[top[x]];
	}
	if (dep[x] > dep[y])
		swap(x, y);
	sum += tr->Query(dfn[x], dfn[y]);
	sum %= p;
	return sum;
}

谢谢喵!

2024/3/29 22:54
加载中...