Luo Gu P4211 [LNOI2014] LCA

Thought interrogation in a differential split into \ (Q (R & lt) -q (L -. 1) \) , offline, sorted by the endpoint.
\ (i, z \) a \ (the LCA \) depth is in fact the root \ (I \) node on the path to the root after adding a whole \ (Z \) the length of the path. A a plus, and a detachable answer a monotonous asked enough.
It seems to be persistent with tree line do online.

#include <cstdio>
#include <algorithm>

const int MAXN = 5e4 + 19, MOD = 201314;

class SegmentTree{
	private:
		struct Node{
			int l, r;
			int val, tag;
		}tr[MAXN << 2];
		void push_up(int node){
			tr[node].val = tr[node << 1].val + tr[node << 1 | 1].val;
			tr[node].val %= MOD;
		}
		void push_down(int node){
			if(tr[node].tag){
				tr[node << 1].val += tr[node].tag * (tr[node << 1].r - tr[node << 1].l + 1);
				tr[node << 1].val %= MOD;
				tr[node << 1].tag += tr[node].tag;
				tr[node << 1].tag %= MOD;
				tr[node << 1 | 1].val += tr[node].tag * (tr[node << 1 | 1].r - tr[node << 1 | 1].l + 1);
				tr[node << 1 | 1].val %= MOD;
				tr[node << 1 | 1].tag += tr[node].tag;
				tr[node << 1 | 1].tag %= MOD;
				tr[node].tag = 0;
			}
		}
		void build(int node, int l, int r){
			tr[node].l = l, tr[node].r = r;
			if(l == r)
				return;
			int mid = (l + r) >> 1;
			build(node << 1, l, mid);
			build(node << 1 | 1, mid + 1, r);
		}
		void modify(int node, int l, int r, const int& val){
			if(tr[node].l >= l && tr[node].r <= r){
				tr[node].val += val * (tr[node].r - tr[node].l + 1) % MOD;
				tr[node].val %= MOD;
				tr[node].tag += val;
				tr[node].tag %= MOD;
				return;
			}
			push_down(node);
			int mid = (tr[node].l + tr[node].r) >> 1;
			if(l <= mid)
				modify(node << 1, l, r, val);
			if(r > mid)
				modify(node << 1 | 1, l, r, val);
			push_up(node);
		}
		int query(int node, int l, int r){
			if(tr[node].l >= l && tr[node].r <= r)
				return tr[node].val;
			push_down(node);
			int mid = (tr[node].l + tr[node].r) >> 1,
				res = 0;
			if(l <= mid)
				res += query(node << 1, l, r);
			if(r > mid)
				res += query(node << 1 | 1, l, r);
			return res;
		}
	public:
		void build(int l, int r){
			build(1, l, r);
		}
		void modify(int l, int r, const int& val){
			modify(1, l, r, val);
		}
		int query(int l, int r){
			return query(1, l, r);
		}
}myTree;

int ans[MAXN];

struct Query{
	int r, z, id, tp, val;
	void set(int _r, int _z, int _id, int _tp){
		r = _r, z = _z, id = _id, tp = _tp;
	}
	void enable(void){
		ans[id] += tp * val;
	}
	bool operator<(const Query& b)const{
		return r < b.r;
	}
}query[MAXN << 1];

int n, q;

struct Edge{
	int to, next;
}edge[MAXN << 1];

int cnt, head[MAXN];

inline void add(int from, int to){
	edge[++cnt].to = to;
	edge[cnt].next = head[from];
	head[from] = cnt;
}

int ind;
int fa[MAXN], son[MAXN], dep[MAXN], size[MAXN], top[MAXN], dfn[MAXN];

void dfs1(int node, int f){
	fa[node] = f, dep[node] = dep[f] + 1, size[node] = 1;
	int __max = 0;
	for(int i = head[node]; i; i = edge[i].next)
		if(edge[i].to != f){
			dfs1(edge[i].to, node);
			size[node] += size[edge[i].to];
			if(size[edge[i].to] > __max)
				__max = size[edge[i].to], son[node] = edge[i].to;
		}
}

void dfs2(int node, int f, int t){
	dfn[node] = ++ind, top[node] = t;
	if(son[node])
		dfs2(son[node], node, t);
	for(int i = head[node]; i; i = edge[i].next)
		if(edge[i].to != f && edge[i].to != son[node])
			dfs2(edge[i].to, node, edge[i].to);
}

void modifyPath(int x, int y, const int& val){
	while(top[x] != top[y]){
		if(dep[top[x]] > dep[top[y]])
			myTree.modify(dfn[top[x]], dfn[x], val), x = fa[top[x]];
		else
			myTree.modify(dfn[top[y]], dfn[y], val), y = fa[top[y]];
	}
	if(dep[x] < dep[y])
		myTree.modify(dfn[x], dfn[y], val);
	else
		myTree.modify(dfn[y], dfn[x], val);
}

int queryPath(int x, int y){
	int res = 0;
	while(top[x] != top[y]){
		if(dep[top[x]] > dep[top[y]])
			res += myTree.query(dfn[top[x]], dfn[x]), x = fa[top[x]];
		else
			res += myTree.query(dfn[top[y]], dfn[y]), y = fa[top[y]];
		res %= MOD;
	}
	if(dep[x] < dep[y])
		res += myTree.query(dfn[x], dfn[y]);
	else
		res += myTree.query(dfn[y], dfn[x]);
	return res % MOD;
}

int main(){
	std::scanf("%d%d", &n, &q);
	myTree.build(1, n);
	for(int u, i = 2; i <= n; ++i){
		std::scanf("%d", &u);
		add(u + 1, i);
	}
	dfs1(1, 0);
	dfs2(1, 0, 1);
	for(int l, r, z, i = 1; i <= q; ++i){
		std::scanf("%d%d%d", &l, &r, &z); ++r, ++z;
		query[i << 1].set(l, z, i, -1);
		query[(i << 1) - 1].set(r, z, i, 1);
	}
	q <<= 1;
	std::sort(query + 1, query + 1 + q);
	for(int fst = 0, i = 1; i <= q; ++i){
		while(fst < query[i].r)
			++fst, modifyPath(1, fst, 1);
		query[i].val = queryPath(1, query[i].z);
		query[i].enable();
	}
	q >>= 1;
	for(int i = 1; i <= q; ++i)
		std::printf("%d\n", (ans[i] % MOD + MOD) % MOD);
	return 0;
}

Guess you like

Origin www.cnblogs.com/natsuka/p/12636509.html