题解 西克

传送门

只会时间 O(nlog2n),空间 O(nlogn)

向上倍增是容易的
向下树剖拆成 log 条链,每条上分别倍增
对每种颜色的点开 vector 按 dfs 序排序以找到某条重链上第一个颜色为 c 的点

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 2000010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, q;
unsigned S1, S2;
vector<int> to[N];
int a[N], b[N], fa[N], ans;
int siz[N], msiz[N], mson[N], top[N], btm[N], id[N], rk[N], dep[N], tot;
unsigned int rnd(){S1*=S2,S2>>=S1&13,S2-=S1,S1^=S2; return ((S1-S2)&(S1+S2))^(S1*S2>>4);}

void dfs1(int u) {
	siz[u]=1;
	for (auto& v:to[u]) {
		dep[v]=dep[u]+1;
		dfs1(v);
		if (siz[v]>msiz[u]) msiz[u]=siz[v], mson[u]=v;
		siz[u]+=siz[v];
	}
}
void dfs2(int u, int t) {
	top[u]=t;
	rk[id[u]=++tot]=u;
	if (!mson[u]) {btm[t]=u; return ;}
	dfs2(mson[u], t);
	for (auto& v:to[u]) if (v!=mson[u])
		dfs2(v, v);
}
int lca(int a, int b) {
	// cout<<"lca: "<<a<<' '<<b<<endl;
	while (top[a]!=top[b]) {
		if (dep[top[a]]<dep[top[b]]) swap(a, b);
		a=fa[top[a]];
	}
	return dep[a]<dep[b]?a:b;
}

// namespace force{
// 	int top, tot;
// 	pair<int, int> sta[N], tem[N];
// 	void solve() {
// 		for (int i=1,x,y; i<=q; ++i) {
// 			x=read(); y=read(); top=tot=0;
// 			while (1) {
// 				if (dep[x]>dep[y]) {
// 					sta[++top]={a[x], b[x]};
// 					if (x==y) break;
// 					x=fa[x];
// 				}
// 				else {
// 					tem[++tot]={a[y], b[y]};
// 					if (x==y) break;
// 					y=fa[y];
// 				}
// 			}
// 			while (tot) sta[++top]=tem[tot--];
// 			int c=sta[1].sec;
// 			for (int j=2; j<=top; ++j) if (sta[j].fir==c) c=sta[j].sec;
// 			ans^=c;
// 		}
// 		printf("%d\n", ans);
// 	}
// }

// namespace task1{
// 	#define ls(p) lson[p]
// 	#define rs(p) rson[p]
// 	vector<pair<int, int>> sta;
// 	int rot[N], lson[N*60], rson[N*60], dat[N*60], tot, ans;
// 	int up[22][N], down[22][N], ulen[N], dlen[N], lst[N], lg[N];
// 	void upd(int& p1, int p2, int tl, int tr, int pos, int val) {
// 		// cout<<"upd: "<<tl<<' '<<tr<<' '<<pos<<endl;
// 		p1=++tot;
// 		if (tl==tr) {dat[p1]=val; return ;}
// 		int mid=(tl+tr)>>1;
// 		if (pos<=mid) upd(ls(p1), ls(p2), tl, mid, pos, val), rs(p1)=rs(p2);
// 		else upd(rs(p1), rs(p2), mid+1, tr, pos, val), ls(p1)=ls(p2);
// 	}
// 	int query(int p, int tl, int tr, int pos) {
// 		if (!p) return 0;
// 		if (tl==tr) return dat[p];
// 		int mid=(tl+tr)>>1;
// 		if (pos<=mid) return query(ls(p), tl, mid, pos);
// 		else return query(rs(p), mid+1, tr, pos);
// 	}
// 	void show(int p, int tl, int tr) {
// 		if (tl==tr) {cout<<dat[p]; return ;}
// 		int mid=(tl+tr)>>1;
// 		show(ls(p), tl, mid); show(rs(p), mid+1, tr);
// 	}
// 	void dfs3(int u) {
// 		ulen[u]=ulen[up[0][u]=lst[b[u]]]+1;
// 		for (int i=1; ulen[u]>=1<<i; ++i)
// 			up[i][u]=up[i-1][up[i-1][u]];
// 		int bkp=lst[a[u]]; lst[a[u]]=u;
// 		for (auto& v:to[u]) dfs3(v);
// 		lst[a[u]]=bkp;
// 	}
// 	void solve() {
// 		dfs3(1);
// 		for (int i=1; i<=n; ++i) if (!mson[i]) {
// 			// cout<<"leaf: "<<i<<endl;
// 			for (int u=i,lst=0; ; lst=u,u=fa[u]) {
// 				// cout<<"u: "<<u<<endl;
// 				dlen[u]=dlen[down[0][u]=query(rot[lst], 1, n, b[u])]+1;
// 				for (int j=1; dlen[u]>=1<<j; ++j)
// 					down[j][u]=down[j-1][down[j-1][u]];
// 				upd(rot[u], rot[lst], 1, n, a[u], u);
// 				if (top[u]==u) break;
// 			}
// 		}
// 		for (int i=1; i<=n; ++i) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
// 		for (int i=1,x,y; i<=q; ++i) {
// 			x=read(); y=read();
// 			if (x==y) {
// 				// cout<<"col: "<<b[x]<<endl;
// 				ans^=b[x]; continue;
// 			}
// 			int t=lca(x, y);
// 			// cout<<"lca: "<<t<<endl;
// 			for (int j=lg[ulen[x]]-1; ~j; --j)
// 				if (up[j][x] && dep[up[j][x]]>=dep[t])
// 					x=up[j][x];
// 			int col=b[x]; sta.clear();
// 			// cout<<"after up, at "<<x<<" and col="<<col<<endl;
// 			while (top[y]!=top[t]) {
// 				sta.pb({top[y], y});
// 				y=fa[top[y]];
// 			}
// 			if (t!=y) sta.pb({mson[t], y});
// 			// cout<<"sta: "; for (auto& it:sta) cout<<"("<<it.fir<<','<<it.sec<<") "; cout<<endl;
// 			while (sta.size()) {
// 				int suf=query(rot[sta.back().fir], 1, n, col);
// 				// cout<<"query: "<<suf<<endl;
// 				// cout<<"seg: "; show(rot[sta.back().fir], 1, n); cout<<endl;
// 				if (!suf || dep[suf]>dep[sta.back().sec]) {sta.pop_back(); continue;}
// 				x=suf;
// 				for (int j=lg[dlen[x]]-1; ~j; --j)
// 					if (down[j][x] && dep[down[j][x]]<=dep[sta.back().sec])
// 						x=down[j][x];
// 				// cout<<"x: "<<x<<endl;
// 				col=b[x]; sta.pop_back();
// 			}
// 			ans^=col;
// 			// cout<<"col: "<<col<<endl;
// 		}
// 		printf("%d\n", ans);
// 	}
// }

namespace task{
	vector<int> buc[N];
	vector<pair<int, int>> sta;
	int up[22][N], down[22][N], ulen[N], dlen[N], lst[N], lg[N], ans;
	void dfs3(int u) {
		ulen[u]=ulen[up[0][u]=lst[b[u]]]+1;
		for (int i=1; ulen[u]>=1<<i; ++i)
			up[i][u]=up[i-1][up[i-1][u]];
		int bkp=lst[a[u]]; lst[a[u]]=u;
		for (auto& v:to[u]) dfs3(v);
		lst[a[u]]=bkp;
	}
	int query(int l, int r, int col) {
		auto it=lower_bound(buc[col].begin(), buc[col].end(), l);
		if (it==buc[col].end() || *it>r) return 0;
		else return rk[*it];
	}
	void solve() {
		// cout<<double(sizeof(up)*2+sizeof(ulen)*17)/1000/1000<<endl; exit(0);
		dfs3(1);
		// cout<<"id: "; for (int i=1; i<=n; ++i) cout<<id[i]<<' '; cout<<endl;
		for (int i=1; i<=n; ++i) buc[a[i]].pb(id[i]);
		for (int i=1; i<=n; ++i) {
			sort(buc[i].begin(), buc[i].end());
			// cout<<"buc: "; for (auto& it:buc[i]) cout<<it<<' '; cout<<endl;
		}
		for (int i=1; i<=n; ++i) if (!mson[i]) {
			// cout<<"leaf: "<<i<<endl;
			for (int u=i,lst=0; ; lst=u,u=fa[u]) {
				// cout<<"u: "<<u<<endl;
				dlen[u]=dlen[down[0][u]=query(id[u], id[i], b[u])]+1;
				// cout<<down[0][u]<<endl;
				for (int j=1; dlen[u]>=1<<j; ++j)
					down[j][u]=down[j-1][down[j-1][u]];
				// upd(rot[u], rot[lst], 1, n, a[u], u);
				if (top[u]==u) break;
			}
		}
		for (int i=1; i<=n; ++i) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
		for (int i=1,x,y; i<=q; ++i) {
			x=read(); y=read();
			if (x==y) {
				// cout<<"col: "<<b[x]<<endl;
				ans^=b[x]; continue;
			}
			int t=lca(x, y);
			// cout<<"lca: "<<t<<endl;
			for (int j=lg[ulen[x]]-1; ~j; --j)
				if (up[j][x] && dep[up[j][x]]>=dep[t])
					x=up[j][x];
			int col=b[x]; sta.clear();
			// cout<<"after up, at "<<x<<" and col="<<col<<endl;
			while (top[y]!=top[t]) {
				sta.pb({top[y], y});
				y=fa[top[y]];
			}
			if (t!=y) sta.pb({mson[t], y});
			// cout<<"sta: "; for (auto& it:sta) cout<<"("<<it.fir<<','<<it.sec<<") "; cout<<endl;
			while (sta.size()) {
				int suf=query(id[sta.back().fir], id[sta.back().sec], col);
				// cout<<"query: "<<suf<<endl;
				// cout<<"seg: "; show(rot[sta.back().fir], 1, n); cout<<endl;
				if (!suf) {sta.pop_back(); continue;}
				x=suf;
				for (int j=lg[dlen[x]]-1; ~j; --j)
					if (down[j][x] && dep[down[j][x]]<=dep[sta.back().sec])
						x=down[j][x];
				// cout<<"x: "<<x<<endl;
				col=b[x]; sta.pop_back();
			}
			ans^=col;
			// cout<<"col: "<<col<<endl;
		}
		printf("%d\n", ans);
	}
}

signed main()
{
	freopen("shik.in", "r", stdin);
	freopen("shik.out", "w", stdout);

	n=read(); q=read(); S1=read(); S2=read();
	for (int i=1; i<=min(n, 500000); ++i) a[i]=read(), b[i]=read();
	for (int i=500001; i<=n; ++i) {
		a[i]=rnd()%n+1, b[i]=a[rnd()%500000+1];
		if (a[i]==b[i] && ++a[i]>n) a[i]=1;
	}
	for (int i=2; i<=n; ++i) to[fa[i]=read()].pb(i);
	dep[1]=1; dfs1(1); dfs2(1, 1);
	// force::solve();
	task::solve();

	return 0;
}
posted @   Administrator-09  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2021-08-02 题解 Strange Housing
点击右上角即可分享
微信分享提示