CF1007D Ants 题解
题意
有一棵包含
思路
很好的一道树剖优化建图的题。
首先看到题目首先想到 2-SAT 直接建图求方案,但是稍加分析会发现边数高达
考虑使用数据结构来减少边的数量,由于每只蚂蚁给的都是树上的一条链,考虑使用树链剖分优化。
具体的,将一条链拆成
但是这样做会发现样例过不去,因为如果一个区间选择颜色
总的时间空间复杂度均为
Code
#include <bits/stdc++.h>
#define ret return
#define pb push_back
#define mid (l+r>>1)
using namespace std;
int read(){int s=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}ret s*f;}
namespace T{
const int N=1e5+1;vector<int> v[N];
int dep[N],siz[N],son[N],f[N],dfn[N],tot,top[N];
void dfs(int u,int fa){
dep[u]=dep[f[u]=fa]+1,siz[u]=1;
for(auto i:v[u]){
if(i==fa)continue;
dfs(i,u);siz[u]+=siz[i];
if(siz[son[u]]<siz[i])son[u]=i;
}
}
void init(int u,int now){
top[u]=now,dfn[u]=++tot;
if(son[u])init(son[u],now);
for(auto i:v[u])if(!top[i])init(i,i);
}
}
const int N=4e6+10;
namespace G{
int vis[N],dfn[N],low[N],bl[N],tot,cnt;stack<int> stk;vector<int> v[N];
void tarjan(int u){
int d;vis[u]=1,low[u]=dfn[u]=++tot;stk.push(u);
for(auto i:v[u]){
if(!dfn[i]){tarjan(i);low[u]=min(low[u],low[i]);}
else if(vis[i])low[u]=min(low[u],dfn[i]);
}
if(dfn[u]==low[u]){++cnt;do{d=stk.top();stk.pop();bl[d]=cnt;vis[d]=0;}while(u!=d);}
}
}
namespace S{
int ls[N],rs[N],f[N],tot,rup,rdown;
vector<int> v[N],p[N],n[N];
void build(int l,int r,int &q,int op){
q=++tot;if(l==r)ret;
build(l,mid,ls[q],op);f[ls[q]]=q;
build(mid+1,r,rs[q],op);f[rs[q]]=q;
if(op){G::v[ls[q]].pb(q);G::v[rs[q]].pb(q);}
else{G::v[q].pb(ls[q]);G::v[q].pb(rs[q]);}
}
void init(int n,int m){tot=m*2+1;build(1,n,rup,1);build(1,n,rdown,0);}
void change(int l,int r,int q,int x,int y,int in,int out,int op){
if(x>y)ret;
if(l==x&&r==y){
if(op){if(ls[q])G::v[in].pb(ls[q]);if(rs[q])G::v[in].pb(rs[q]);G::v[q].pb(out);}
else{if(f[q])G::v[in].pb(f[q]);G::v[q].pb(out);v[q].pb(out);}ret;
}
if(y<=mid)ret change(l,mid,ls[q],x,y,in,out,op);
if(x>mid)ret change(mid+1,r,rs[q],x,y,in,out,op);
change(l,mid,ls[q],x,mid,in,out,op);
change(mid+1,r,rs[q],mid+1,y,in,out,op);
}
void add(int x,int y,int in,int out,int n){
while(T::top[x]!=T::top[y]){
if(T::dep[T::top[x]]<T::dep[T::top[y]])swap(x,y);
change(1,n,rup,T::dfn[T::top[x]],T::dfn[x],in,out,0);
change(1,n,rdown,T::dfn[T::top[x]],T::dfn[x],in,out,1);x=T::f[T::top[x]];
}
if(T::dep[x]>T::dep[y])swap(x,y);
change(1,n,rup,T::dfn[x]+1,T::dfn[y],in,out,0);
change(1,n,rdown,T::dfn[x]+1,T::dfn[y],in,out,1);
}
void update(int m){
int cnt=tot;
for(int i=m*2+2;i<=cnt;i++){
int len=v[i].size();
p[i].resize(len);
n[i].resize(len);
for(int j=0;j<len;j++){
p[i][j]=++tot;
if(j!=0)G::v[p[i][j]].pb(p[i][j-1]);
G::v[p[i][j]].pb(v[i][j]);
}
for(int j=len-1;j>=0;j--){
n[i][j]=++tot;
if(j!=len-1)G::v[n[i][j]].pb(n[i][j+1]);
G::v[n[i][j]].pb(v[i][j]);
}
for(int j=0;j<len;j++){
if(j!=0)G::v[v[i][j]^1].pb(p[i][j-1]);
if(j!=len-1)G::v[v[i][j]^1].pb(n[i][j+1]);
}
}
}
}
void solve(){
int n=read(),x,y;
for(int i=1;i<n;i++){int x=read(),y=read();T::v[x].pb(y);T::v[y].pb(x);}
T::dfs(1,0);T::init(1,1);int m=read();S::init(n,m);
for(int i=1;i<=m;i++){
x=read(),y=read();S::add(x,y,i*2,i*2+1,n);
x=read(),y=read();S::add(x,y,i*2+1,i*2,n);
}
S::update(m);
for(int i=2;i<=m*2+1;i++)if(!G::dfn[i])G::tarjan(i);
for(int i=1;i<=m;i++)if(G::bl[i*2]==G::bl[i*2+1]){puts("NO");ret;}
puts("YES");for(int i=1;i<=m;i++)printf("%d\n",G::bl[i*2]<G::bl[i*2+1]?1:2);
}
signed main(){solve();ret 0;}