社区讨论

求助卡常

P7126[Ynoi2008] rdCcot参与者 3已保存回复 8

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
7 条
当前快照
1 份
快照标识符
@mk54zfe4
此快照首次捕获于
2026/01/08 15:39
上个月
此快照最后确认于
2026/01/10 21:40
上个月
查看原帖
rt,大致思路和第一篇题解一样,但是用的线段树,常数大很多,qoj 能跑到 80pts80pts,洛谷只有 5656
CPP
#include<bits/stdc++.h>
using namespace std;
inline int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-')	f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9') {
		x = (x << 3) + (x << 1) + ch - '0';
		ch = getchar();
	}
	return x * f;
}
int n, m, C, b[300005], head[300005], tail[600005], nxt[600005], tot, pre[300005], suf[300005], siz[300005];
inline void add_edge(int u, int v) {
	tail[++tot] = v;
	nxt[tot] = head[u];
	head[u] = tot;
	tail[++tot] = u;
	nxt[tot] = head[v];
	head[v] = tot;
	return;
}
int qB[300005], hB = 1, tB;
inline void bfs() {
	int bfn = 0;
	qB[++tB] = 1;
	b[1] = ++bfn;
	while(hB <= tB) {
		int p = qB[hB++];
		for(int i = head[p]; i; i = nxt[i]) {
			int ed = tail[i];
			if(b[ed])	continue;
			b[ed] = ++bfn;
			qB[++tB] = ed;
		}
	}
	return;
}
vector<int> rub;
bool flag[1500005];
	int val[1500005], Ans;
	bool isans;
	inline void pushup(int p) {
		val[p] = min(val[p << 1], val[p << 1 | 1]);
		return;
	}
	inline void build(int p, int l, int r) {
		val[p] = 1e9;
		if(l == r)	return;
		int mid = l + r >> 1;
		build(p << 1, l, mid);
		build(p << 1 | 1, mid + 1, r);
		return;
	}
	inline void ins(int p, int l, int r, int k, int x) {
		if(!flag[p])	rub.push_back(p);
		flag[p] = true;
		if(l == r) {
			val[p] = x;
			return;
		}
		int mid = l + r >> 1;
		if(k <= mid)	ins(p << 1, l, mid, k, x);
		else	ins(p << 1 | 1, mid + 1, r, k, x);
		pushup(p);
		return;
	}
	inline int ask1(int p, int l, int r, int x) {
		if(l == r)	return l;
		int mid = l + r >> 1;
		if(val[p << 1] <= x)	return ask1(p << 1, l, mid, x);
		return ask1(p << 1 | 1, mid + 1, r, x);
	}
	inline int ask2(int p, int l, int r, int x) {
		if(l == r)	return l;
		int mid = l + r >> 1;
		if(val[p << 1 | 1] <= x)	return ask2(p << 1 | 1, mid + 1, r, x);
		return ask2(p << 1, l, mid, x);
	}
	inline void query1(int p, int l, int r, int L, int R, int x) {
		if(L > R)	return;
		if(isans)	return;
		if(L <= l && r <= R) {
			if(val[p] > x)	return;
			isans = true;
			Ans = ask1(p, l, r, x);
			return; 
		}
		int mid = l + r >> 1;
		if(L <= mid)	query1(p << 1, l, mid, L, R, x);
		if(R > mid && !isans)	query1(p << 1 | 1, mid + 1, r, L, R, x);
		return;
	}
	inline void query2(int p, int l, int r, int L, int R, int x) {
		if(L > R)	return;
		if(isans)	return;
		if(L <= l && r <= R) {
			if(val[p] > x)	return;
			isans = true;
			Ans = ask2(p, l, r, x);
			return; 
		}
		int mid = l + r >> 1;
		if(R > mid)	query2(p << 1 | 1, mid + 1, r, L, R, x);
		if(L <= mid && !isans)	query2(p << 1, l, mid, L, R, x);
		return;
	}
	inline int Qpr(int id, int x) {
		isans = false;
		Ans = 0;
		query2(1, 1, n, 1, id - 1, x);
		return Ans;
	}
	inline int Qnx(int id, int x) {
		isans = false;
		Ans = n + 1;
		query1(1, 1, n, id + 1, n, x);
		return Ans;
	}
namespace Solve {
	int rt, mxsiz[300005], nowsiz, dis[300005];
	bool vis[300005];
	vector<int> vc;
	inline void getrt(int x, int fa) {
		mxsiz[x] = 0;
		siz[x] = 1;
		for(int i = head[x]; i; i = nxt[i]) {
			int ed = tail[i];
			if(ed == fa || vis[ed])	continue;
			getrt(ed, x);
			siz[x] += siz[ed];
			mxsiz[x] = max(mxsiz[x], siz[ed]);
		}
		mxsiz[x] = max(mxsiz[x], nowsiz - siz[x]);
		if(mxsiz[x] < mxsiz[rt])	rt = x;
		return;
	}
	inline void dfs(int x, int fa) {
		dis[x] = dis[fa] + 1;
		vc.push_back(x);
		for(int i = head[x]; i; i = nxt[i]) {
			int ed = tail[i];
			if(ed == fa || vis[ed])	continue;
			dfs(ed, x);
		}
		return;
	}
	inline bool cmp(int x, int y) {
		return b[x] < b[y];
	}
	inline void work(int x) {
		dis[0] = -1;
		vc.clear();
		dfs(x, 0);
		rub.clear();
		sort(vc.begin(), vc.end(), cmp); 
		for(auto id : vc) {
			pre[id] = max(pre[id], Qpr(id, C - dis[id]));
			suf[id] = min(suf[id], Qnx(id, C - dis[id]));
			if(dis[id] <= C)	ins(1, 1, n, id, dis[id]);
		}
		for(auto x : rub) {
			val[x] = 1e9;
			flag[x] = false;
		}
	//	cout<<endl;
		return;
	}
	inline void solve(int x) {
		if(nowsiz > 1)	work(x);
		vis[x] = true;
		int now = nowsiz;
//		cout<<x<<" "<<nowsiz<<endl; 
		for(int i = head[x]; i; i = nxt[i]) {
			int ed = tail[i];
			rt = 0;
			mxsiz[0] = 1e9;
			if(vis[ed])	continue;
			if(siz[ed] < siz[x])	nowsiz = siz[ed];
			else	nowsiz = now - siz[x];
			getrt(ed, x);
			solve(rt);
		}
		return;
	}
}
struct node {
	int l, r, id;
}que[600005];
int ans[600005], tr[300005];
inline int lowbit(int x) {
	return x & -x;
}
inline void add(int x, int y) {
	++x;
	while(x <= n + 2) {
		tr[x] += y;
		x += lowbit(x);
	}
	return;
}
inline int ask(int x) {
	++x;
	int res = 0;
	while(x) {
		res += tr[x];
		x -= lowbit(x);
	}
	return res;
}
vector<node> vc1[300005], vc2[300005];
vector<pair<int, int>> tag[300005];
int main() {
	n = read(); m = read(); C = read();
	for(int i = 1; i <= n; ++i) {
		pre[i] = 0; suf[i] = n + 1;
	}
	for(int i = 2; i <= n; ++i) {
		int fa = read();
		add_edge(fa, i);
	}
	bfs();
	Solve::rt = 0;
	Solve::nowsiz = n; 
	Solve::mxsiz[0] = 1e9;
	Solve::getrt(1, 0);
	build(1, 1, n);
	Solve::solve(Solve::rt);
//	for(int i = 1; i <= n; ++i)	cout<<pre[i]<<" "<<suf[i]<<endl;
	for(int i = 1; i <= m; ++i) {
		que[i].l = read(); que[i].r = read(); que[i].id = i;
		vc1[que[i].l].push_back(que[i]);
		vc2[que[i].r].push_back(que[i]);
	}
	for(int i = 1; i <= n; ++i) {
		tag[i].push_back(make_pair(i, 1));
		tag[suf[i]].push_back(make_pair(i, -1));
	}
	for(int i = 1; i <= n; ++i) {
		for(auto qu : vc1[i]) {
			ans[qu.id] -= ask(n + 1) - ask(qu.r);
		}
		add(suf[i], 1);
	}
	memset(tr, 0, sizeof tr);
	for(int i = 1; i <= n; ++i) {
		for(auto x : tag[i]) {
			if(x.second == 1)	add(pre[x.first], 1);
			else	add(pre[x.first], -1);
		}
		for(auto qu : vc2[i]) {
			ans[qu.id] += ask(qu.l - 1);
		}
	}
	for(int i = 1; i <= m; ++i) {
		printf("%d\n", ans[i]);
	}
	return 0;
} 

回复

8 条回复,欢迎继续交流。

正在加载回复...