题目链接:http://codeforces.com/contest/1083/problem/C
用线段树维护树上路径,然后通过lca计算距离来合并
代码:
#include<bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN=2e5+5;
const int DEG=20;
vector<int> E[MAXN];
int p[MAXN],deg[MAXN],pos[MAXN];
int fa[MAXN][DEG];
void dfs(int now,int f=1)
{
fa[now][0]=f;
deg[now]=deg[f]+1;
for(int i=1;i<DEG;i++)
fa[now][i]=fa[fa[now][i-1]][i-1];
for(int v:E[now])
{
if(v==f) continue;
dfs(v,now);
}
}
int lca(int u,int v)
{
if(deg[u]>deg[v])swap(u,v);
int hu=deg[u],hv=deg[v];
int tu=u,tv=v;
for(int det=hv-hu,i=0;det;det>>=1,i++)
if(det&1)
tv=fa[tv][i];
if(tu==tv)return tu;
for(int i=DEG-1;i>=0;i--)
{
if(fa[tu][i]==fa[tv][i])
continue;
tu=fa[tu][i];
tv=fa[tv][i];
}
return fa[tu][0];
}
int dist(int u,int v)
{
int l=lca(u,v);
return deg[u]+deg[v]-2*deg[l];
}
struct seg
{
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
pii tr[MAXN<<2];
pii merge(pii now,int c)
{
if(now.xx<0||c<0) return mp(-1,-1);
int a=now.xx,b=now.yy;
int dab=dist(a,b);
int dac=dist(a,c);
int dbc=dist(b,c);
if(dab+dbc==dac) return mp(a,c);
if(dab+dac==dbc) return mp(b,c);
if(dbc+dac==dab) return mp(a,b);
return mp(-1,-1);
}
pii merge(pii p1,pii p2)
{
if(p1.xx<0||p2.xx<0) return mp(-1,-1);
pii x=merge(p1,p2.xx);
if(x.xx<0) return mp(-1,-1);
return merge(x,p2.yy);
}
void push_up(int rt)
{
tr[rt]=merge(tr[rt<<1],tr[rt<<1|1]);
}
void build(int l,int r,int rt)
{
if(l==r)
{
tr[rt]=mp(pos[l],pos[l]);
return ;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
push_up(rt);
}
void update(int p,int l,int r,int rt)
{
if(l==r)
{
tr[rt]=mp(pos[p],pos[p]);
return ;
}
int mid=(l+r)>>1;
if(p<=mid) update(p,lson);
if(mid<p) update(p,rson);
push_up(rt);
}
int query(pii &pre,int l,int r,int rt)
{
if(tr[rt].xx>=0)
{
if(pre.xx<0)
{
pre=tr[rt];
return r+1;
}
pii x=merge(pre,tr[rt]);
if(x.xx>=0)
{
pre=x;
return r+1;
}
}
if(l==r) return l;
int mid=(l+r)>>1;
int ret=query(pre,lson);
if(ret<=mid) return ret;
return query(pre,rson);
}
}se;
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&p[i]);
pos[p[i]]=i;
}
for(int i=2;i<=n;i++)
{
int x;
scanf("%d",&x);
E[x].pb(i);E[i].pb(x);
}
dfs(1);
se.build(0,n-1,1);
int q;
scanf("%d",&q);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x,y;
scanf("%d%d",&x,&y);
swap(p[x],p[y]);
pos[p[x]]=x;
pos[p[y]]=y;
se.update(p[x],0,n-1,1);
se.update(p[y],0,n-1,1);
}
else
{
pii pre=mp(-1,-1);
int res=se.query(pre,0,n-1,1);
printf("%d\n",res);
}
}
return 0;
}