题目
t(t<=1e4)组样例,每次给n(n<=3e5)个点的树,和一个初始dfs序序列,
q(q<=1e5)次交换,每次交换dfs序序列上的两个位置,问交换完是不是还是合法dfs序
思路来源
gongkoufadongji代码
题解
这题做法很多,很多也都是乱搞,补一个性质的做法
做法1
性质做法:lca(p[i],p[i-1])=fa(p[i])
考虑dfs序,每次要么是下钻一个点,要么是搜完一棵子树,跳到另一棵子树的根上
(1)下钻一个点的时候,满足a[i]是a[i-1]的儿子
(2)搜完一棵子树,跳到另一棵子树的根上,满足a[i]的父亲是a[i-1]的祖先,且a[i-1]是叶子
所以,只需满足性质的点是n-1个点,就是合法的dfs序
当然你也可以把相邻点距离也维护上,这样更卡不掉,距离总和是2n-2
做法2
做法2是赛中的想法,是一个乱搞,但是也卡不掉,感觉也挺对的
每个点u维护一个set,存所有直连儿子v的dfn,
考虑dfs序,dfn[u]一定是最小的直连dfn[v]减1,
最大的直连dfn[v]不会超过dfn[u]+sz[u]-sz[v]
https://codeforces.com/contest/2002/submission/275838298
代码1(dfs序性质 lca)
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define lowbit(x) (x&(-x))
#define ull unsigned long long
#define pii pair<int,int>
using namespace std;
const string yes="Yes\n",no="No\n";
const int N = 1000005,inf = 2e18,mod=1000000007;
int n,q;
vector<int>p[300005];
int a[300005];
int st[300005][20];
int dep[300005];
void dfs(int u,int fa){
dep[u]=dep[fa]+1;
st[u][0]=fa;
for(int i=1;i<20;i++){
st[u][i]=st[st[u][i-1]][i-1];
}
for(auto v:p[u]){
if(v==fa)continue;
dfs(v,u);
}
}
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
for(int i=19;~i;i--){
if(dep[st[u][i]]>=dep[v])u=st[u][i];
}
if(u==v)return u;
for(int i=19;~i;i--){
if(st[u][i]==st[v][i])continue;
u=st[u][i];
v=st[v][i];
}
return st[u][0];
}
int getdis(int u,int v){
return min(u,v)>0?dep[u]+dep[v]-2*dep[lca(u,v)]:0;
}
int ck1(int x){
return x<n&&x>0?lca(a[x],a[x+1])==a[x+1]:0;
}
void solve(){
cin>>n>>q;
for(int i=1;i<=n;i++){
p[i].clear();
}
for(int i=2;i<=n;i++){
int f;cin>>f;
p[f].push_back(i);
}
dfs(1,0);
int len=0,sum=0;
for(int i=1;i<=n;i++){
cin>>a[i];
len+=getdis(a[i],a[i-1]);
sum+=ck1(i-1);
}
a[n+1]=0;
while(q--){
int u,v;cin>>u>>v;
if(u>v)swap(u,v);
len-=getdis(a[u],a[u-1]);
len-=getdis(a[u],a[u+1]);
len-=getdis(a[v],a[v-1]);
len-=getdis(a[v],a[v+1]);
sum-=ck1(u-1);
sum-=ck1(u);
if(u+1!=v)sum-=ck1(v-1);
sum-=ck1(v);
swap(a[u],a[v]);
len+=getdis(a[u],a[u-1]);
len+=getdis(a[u],a[u+1]);
len+=getdis(a[v],a[v-1]);
len+=getdis(a[v],a[v+1]);
sum+=ck1(u-1);
sum+=ck1(u);
if(u+1!=v)sum+=ck1(v-1);
sum+=ck1(v);
// cout<<len<<"???\n";
if(sum==0&&len+dep[a[n]]-1==2*n-2){
cout<<yes;
}
else{
cout<<no;
}
}
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cout<<fixed<<setprecision(12);
int t=1;
cin>>t;
while (t--)solve();
}
代码2(赛中想法)
#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
const int N=3e5+10;
int t,n,Q,f,p[N],par[N],dfn[N],sz[N],x,y;
int no[N],cnt;
vector<int>e[N];
set<P>q[N];
void dfs(int u){
sz[u]=1;
for(auto &v:e[u]){
dfs(v);
sz[u]+=sz[v];
}
}
void rb(int i){
if(!i)return;
if(q[i].empty())return;
cnt-=no[i];
int mn=(*q[i].begin()).fi;
int mx=(*q[i].rbegin()).fi,w=(*q[i].rbegin()).se;
if(dfn[i]!=mn-1 || mx<=dfn[i] || mx>dfn[i]+sz[i]-w)no[i]=1;
else no[i]=0;
cnt+=no[i];
}
int main(){
sci(t);
while(t--){
sci(n);sci(Q);
rep(i,0,n)q[i].clear(),e[i].clear(),no[i]=0;
rep(i,2,n){
sci(f);
e[f].pb(i);
par[i]=f;
}
dfs(1);
rep(i,1,n){
sci(p[i]);
int u=p[i];
dfn[u]=i;
f=par[u];
if(f)q[f].insert(P(i,sz[u]));
}
cnt=0;
rep(i,1,n){
if(q[i].empty())continue;
int mn=(*q[i].begin()).fi;
int mx=(*q[i].rbegin()).fi,w=(*q[i].rbegin()).se;
if(dfn[i]!=mn-1 || mx<=dfn[i] || mx>dfn[i]+sz[i]-w)no[i]=1;
else no[i]=0;
cnt+=no[i];
}
while(Q--){
sci(x);sci(y);
int u=p[x],v=p[y];
int fu=par[u],fv=par[v];
if(fu)q[fu].erase(P(dfn[u],sz[u]));
if(fv)q[fv].erase(P(dfn[v],sz[v]));
swap(dfn[u],dfn[v]);
swap(p[x],p[y]);
if(fu)q[fu].insert(P(dfn[u],sz[u]));
if(fv)q[fv].insert(P(dfn[v],sz[v]));
rb(fu);rb(fv);rb(u);rb(v);
//rep(i,1,n)printf("i:%d dfn:%d no:%d\n",i,dfn[i],no[i]);
puts((cnt || p[1]!=1)?"NO":"YES");
//dfn[u]=x;dfn[v]=y;
}
}
return 0;
}