版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/86129199
题意:
分析:
翻译一下题意:给出两个N个点的树,首先选择A树中的一条边删除,然后将所有包含此边的路径u->v(要求u,v在B树中是相邻的),对应的B树中的边(u,v)删除。
由于扯到了子树,显然可以考虑DFN的方法。
很明显,路径包含关系在DFN中表示为:对于一条边(u,v),假设深度
那么所有包含此边的路径必然满足:
表示进入这个节点时的dfn位置。
表示离开这个节点的dfn位置。
由于每条边最多删除一次,所以有种很直观的方法是:维护当前状况下,是否存在要删除的边,如果有,就暴力找到它并删除。这样就可以巧妙地避免维护哪些边要被删除的信息。
接下来的操作就很简单了:对于B中的每条边,在其两个端点在A树的DFN序的位置,分别插入另一个端点。对A中的边也对应地操作。
然后就是维护区间最小&最大值,每次删除一条边时 ,在 中,找到区间最小&最大值,如果其在 的范围之外,就找到并删除它。
最后的复杂度是
(代码在考场上写的,较丑)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#define SF scanf
#define PF printf
#define MAXN 200010
using namespace std;
vector<int> a[MAXN],b[MAXN],ida[MAXN],idb[MAXN];
void add_edge(int u,int v,int flag,int num){
if(flag==0){
a[u].push_back(v);
a[v].push_back(u);
ida[u].push_back(num);
ida[v].push_back(num);
}
else{
b[u].push_back(v);
b[v].push_back(u);
idb[u].push_back(num);
idb[v].push_back(num);
}
}
int la[MAXN],ra[MAXN],lb[MAXN],rb[MAXN],dfna[MAXN],dfnb[MAXN],rnkb[MAXN],rnka[MAXN];
int cnt;
void dfsa(int x,int fa=0){
dfna[x]=la[x]=++cnt;
rnka[cnt]=x;
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i];
if(u==fa)
continue;
dfsa(u,x);
}
ra[x]=cnt;
}
void dfsb(int x,int fa=0){
dfnb[x]=lb[x]=++cnt;
rnkb[cnt]=x;
for(int i=0;i<int(b[x].size());i++){
int u=b[x][i];
if(u==fa)
continue;
dfsb(u,x);
}
rb[x]=cnt;
}
int rta,rtb,ncnt;
struct node{
int maxl,maxr,posl,posr,pl,pr;
set<pair<int,int> >st;
}tree[MAXN*8];
pair<int,int> Ea[MAXN],Eb[MAXN];
void get_lr(int l,int id){
if(tree[id].st.size()){
tree[id].maxl=tree[id].st.begin()->first;
tree[id].posl=tree[id].st.begin()->second;
tree[id].maxr=tree[id].st.rbegin()->first;
tree[id].posr=tree[id].st.rbegin()->second;
}
else{
tree[id].maxl=tree[id].maxr=tree[id].posl=tree[id].posr=0;
}
}
void update(int id){
int pl=tree[id].pl;
int pr=tree[id].pr;
tree[id].maxl=tree[id].maxr=tree[id].posl=tree[id].posr=0;
if(tree[pr].maxl==0||(tree[pl].maxl<tree[pr].maxl&&tree[pl].maxl!=0)){
tree[id].maxl=tree[pl].maxl;
tree[id].posl=tree[pl].posl;
}
else{
tree[id].maxl=tree[pr].maxl;
tree[id].posl=tree[pr].posl;
}
if(tree[pr].maxr==0||(tree[pl].maxr>tree[pr].maxr&&tree[pl].maxr!=0)){
tree[id].maxr=tree[pl].maxr;
tree[id].posr=tree[pl].posr;
}
else{
tree[id].maxr=tree[pr].maxr;
tree[id].posr=tree[pr].posr;
}
}
void build(int id,int l,int r,int flag){
if(l==r){
if(flag==0){
int x=rnka[l];
for(int i=0;i<int(b[x].size());i++)
tree[id].st.insert(make_pair(dfna[b[x][i]],idb[x][i]));
}
else{
int x=rnkb[l];
for(int i=0;i<int(a[x].size());i++)
tree[id].st.insert(make_pair(dfnb[a[x][i]],ida[x][i]));
}
get_lr(l,id);
return ;
}
int mid=(l+r)>>1;
tree[id].pl=++ncnt;
tree[id].pr=++ncnt;
build(tree[id].pl,l,mid,flag);
build(tree[id].pr,mid+1,r,flag);
update(id);
}
vector<int> print;
int query(int l,int r,int id,int l1,int r1){
if(l==r){
if(tree[id].st.size()==0)
return 0;
if(tree[id].st.begin()->first<l1)
return tree[id].st.begin()->second;
if(tree[id].st.rbegin()->first>r1)
return tree[id].st.rbegin()->second;
return 0;
}
int mid=(l+r)>>1,res=0;
if(l>=l1&&r<=r1){
if(tree[id].maxl!=0&&tree[id].maxl<l1){
if(tree[tree[id].pl].maxl<l1&&tree[tree[id].pl].maxl!=0)
return query(l,mid,tree[id].pl,l1,r1);
else
return query(mid+1,r,tree[id].pr,l1,r1);
}
if(tree[id].maxr!=0&&tree[id].maxr>r1){
if(tree[tree[id].pl].maxr>r1&&tree[tree[id].pl].maxr!=0)
return query(l,mid,tree[id].pl,l1,r1);
else
return query(mid+1,r,tree[id].pr,l1,r1);
}
return 0;
}
if(l1<=mid)
res=query(l,mid,tree[id].pl,l1,r1);
if(res)
return res;
if(r1>mid)
res=query(mid+1,r,tree[id].pr,l1,r1);
return res;
}
void change(int l,int r,int id,int pos,int delx,int dely){
if(l==r){
tree[id].st.erase(make_pair(delx,dely));
get_lr(l,id);
return ;
}
int mid=(l+r)>>1;
if(pos<=mid)
change(l,mid,tree[id].pl,pos,delx,dely);
else
change(mid+1,r,tree[id].pr,pos,delx,dely);
update(id);
}
queue<int> q[2];
int main(){
int n,u,v,k;
SF("%d",&n);
for(int i=2;i<=n;i++){
SF("%d",&u);
v=i;
add_edge(u,v,0,i-1);
Ea[i-1]=make_pair(u,v);
}
for(int i=2;i<=n;i++){
SF("%d",&u);
v=i;
add_edge(u,v,1,i-1);
Eb[i-1]=make_pair(u,v);
}
dfsa(1);
cnt=0;
dfsb(1);
rta=++ncnt;
build(rta,1,n,0);
rtb=++ncnt;
build(rtb,1,n,1);
SF("%d",&k);
change(1,n,rtb,dfnb[Ea[k].first],dfnb[Ea[k].second],k);
change(1,n,rtb,dfnb[Ea[k].second],dfnb[Ea[k].first],k);
q[0].push(k);
int now=0;
while(!q[now].empty()){
while(!q[now].empty()){
int id=q[now].front();
print.push_back(id);
q[now].pop();
if(now==0){
int x=dfna[Ea[id].first]>dfna[Ea[id].first]?Ea[id].first:Ea[id].second;
int idx=query(1,n,rta,la[x],ra[x]);
while(idx){
change(1,n,rta,dfna[Eb[idx].first],dfna[Eb[idx].second],idx);
change(1,n,rta,dfna[Eb[idx].second],dfna[Eb[idx].first],idx);
q[now^1].push(idx);
idx=query(1,n,rta,la[x],ra[x]);
}
}
else{
int x=dfnb[Eb[id].first]>dfnb[Eb[id].first]?Eb[id].first:Eb[id].second;
int idx=query(1,n,rtb,lb[x],rb[x]);
while(idx){
change(1,n,rtb,dfnb[Ea[idx].first],dfnb[Ea[idx].second],idx);
change(1,n,rtb,dfnb[Ea[idx].second],dfnb[Ea[idx].first],idx);
q[now^1].push(idx);
idx=query(1,n,rtb,lb[x],rb[x]);
}
}
}
if(now==0)
PF("Blue\n");
else
PF("Red\n");
sort(print.begin(),print.end());
for(int i=0;i<int(print.size());i++)
PF("%d ",print[i]);
PF("\n");
print.clear();
now^=1;
}
}