题解 西克
只会时间 ,空间
向上倍增是容易的
向下树剖拆成 条链,每条上分别倍增
对每种颜色的点开 vector 按 dfs 序排序以找到某条重链上第一个颜色为 的点
点击查看代码
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2021-08-02 题解 Strange Housing