大神 P2441M 💩🍽️。🤯🤯🤯
考虑这个询问,因为是固定的策略,所以每个钥匙 \(u\) 实际上只会跟路径上后一个同种类的箱子 \(v\) 匹配,并且只要路径包含 \(u,v\),且方向与 \(u\to v\) 同向就一定被统计。
预处理所有的钥匙、箱子对 \((u,v)\),每次从钥匙搜,若第一次满足 \(cnt_{box}=cnt_{key}\) 则所在点 \(v\) 能与钥匙 \(u\) 匹配。
考虑满足条件的路径 \(x\to y\) 限制。
· \(\operatorname{lca}(u,v)\notin \{u,v\}\) 则限制为 \(x\in sub_u\wedge y\in sub_v\)。\(sub\) 是子树集合。
· \(\operatorname{lca}(u,v)=u\) 限制为 \(x\notin sub_w,y\in sub_v(w\in son_u,\mathrm{lca}(w,v)=w)\)
· \(\operatorname{lca}(u,v)=v\) 限制为 \(x\in sub_u,y\notin sub_w(w\in son_v,\mathrm{lca}(w,u)=w)\)
按 dfs 序容易转化为矩阵加单点查询,扫描线即可。
问题在如何求出所有钥匙、箱子对 \((u,v)\)。有性质每种颜色的钥匙数量 \(\le 5\)。但颜色数一大就炸了,考虑实际上有用的节点只有与钥匙同色的点,显然建出该颜色的虚树,则所有虚树总点数是 \(O(n)\) 的,预处理的复杂度也降至 \(O(n)\)。
Takanashi Rikka
#include<bits/stdc++.h>
using namespace std;
#define fin(x) freopen(#x".in","r",stdin)
#define fout(x) freopen(#x".out","w",stdout)
#define fr(x) fin(x),fout(x);o
#define Fr(x,y) fin(x),fout(y)
#define INPUT(_1,_2,FILE,...) FILE
#define IO(...) INPUT(__VA_ARGS__,Fr,fr)(__VA_ARGS__)
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define il inline
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define ll long long
#define ull unsigned long long
#define ve vector
#define intz(x,y) memset((x),(y),sizeof((x)))
template<typename Type>il void cmx(Type &x,Type y){if(y>x)x=y;}
template<typename Type>il void cmn(Type &x,Type y){if(y<x)x=y;}
template<typename Type>
il typename Type::value_type MAX(Type f) {auto res=*f.begin();for(auto i=f.begin();i!=f.end();cmx(res,*i),i++);return res;
}
template<typename Type>
il typename Type::value_type MIN(Type f) {auto res=*f.begin();for(auto i=f.begin();i!=f.end();cmn(res,*i),i++);return res;
}
#define lowbit(x) (x&-x)
#define pcount(x) __builtin_popcountll(x)
const int N=1e6+5;
ve<int>p[N],ky[N],e[N],E[N];
int id[N],tot,dfn[N],ct,lb[N],F[N],d[N],z[N],tp,siz[N],C[N],fl[N];
void dfs(int u,int fa){dfn[u]=++ct,siz[u]=1;d[u]=d[F[u]=fa]+1;int x=lb[fa],y=lb[x];lb[u]=(d[fa]-d[x]==d[x]-d[y]?y:fa);for(int v:e[u])if(v^fa)dfs(v,u),siz[u]+=siz[v];
}
il int lca(int x,int y){if(d[x]<d[y])swap(x,y);while(d[x]>d[y])x=(d[lb[x]]>=d[y]?lb[x]:F[x]);while(x^y)(lb[x]^lb[y]?(x=lb[x],y=lb[y]):(x=F[x],y=F[y]));return x;
}
il void add(int u,int v){E[u].pb(v),E[v].pb(u);}
ve<pii>opt;
void Dfs(int u,int fa,int c,int tv){// cerr<<"*"<<u<<' '<<c<<'\n';if(!c)return opt.pb(mp(tv,u)),void();for(int v:E[u])if(v^fa){int res=c;if(C[v]==C[tv])res+=(fl[v]?1:-1);Dfs(v,u,res,tv);}
}
il int jp(int x,int y){if(d[x]<d[y])swap(x,y);while(d[x]>d[y]+1)x=(d[lb[x]]>=d[y]+1?lb[x]:F[x]);return x;
}
struct optr{int l,r,x;};
ve<optr>q[N],qry[N];
int t[N],n,m,ans[N];
il void upd(int x,int d){for(;x<=n;x+=lowbit(x))t[x]+=d;}
il int ask(int x){int res=0;for(;x;x-=lowbit(x))res+=t[x];return res;}
il void update(int l,int r,int x){upd(l,x),upd(r+1,-x);}
void UesugiErii(){cin>>n>>m;for(int i=1,c;i<=n;i++){cin>>fl[i]>>c,--fl[i],C[i]=c;if(!fl[i])ky[c].pb(i);else p[c].pb(i);}for(int i=1,u,v;i<n;i++)cin>>u>>v,e[u].pb(v),e[v].pb(u);dfs(1,0);for(int col=1;col<=n;col++){ve<int>q;tot=0;for(int j:p[col])id[++tot]=j;for(int j:ky[col])id[++tot]=j;sort(id+1,id+1+tot,[&](int x,int y){return dfn[x]<dfn[y];});z[tp=1]=1,E[1].clear(),q.pb(1);for(int i=1;i<=tot;i++){if(id[i]==1)continue;int lc=lca(z[tp],id[i]);if(lc!=z[tp]){while(dfn[z[tp-1]]>dfn[lc])add(z[tp-1],z[tp]),--tp;if(lc!=z[tp-1])E[lc].clear(),add(lc,z[tp]),z[tp]=lc,q.pb(lc);else add(lc,z[tp]),--tp;}E[id[i]].clear();z[++tp]=id[i];q.pb(id[i]);}for(int i=1;i<tp;i++)add(z[i],z[i+1]);for(int i:ky[col])Dfs(i,0,(fl[i]?1:-1),i);}// for(pii x:opt)cerr<<x.fi<<' '<<x.se<<'\n';for(pii x:opt){int lc=lca(x.fi,x.se);if(lc!=x.fi&&lc!=x.se)q[dfn[x.fi]].pb({dfn[x.se],dfn[x.se]+siz[x.se]-1,1}),q[dfn[x.fi]+siz[x.fi]].pb({dfn[x.se],dfn[x.se]+siz[x.se]-1,-1});else if(lc==x.fi){q[1].pb({dfn[x.se],dfn[x.se]+siz[x.se]-1,1});int v=jp(x.se,x.fi);q[dfn[v]].pb({dfn[x.se],dfn[x.se]+siz[x.se]-1,-1}),q[dfn[v]+siz[v]].pb({dfn[x.se],dfn[x.se]+siz[x.se]-1,1});}else{q[dfn[x.fi]].pb({1,n,1});q[dfn[x.fi]+siz[x.fi]].pb({1,n,-1});int v=jp(x.se,x.fi);q[dfn[x.fi]].pb({dfn[v],dfn[v]+siz[v]-1,-1}),q[dfn[x.fi]+siz[x.fi]].pb({dfn[v],dfn[v]+siz[v]-1,1});}}for(int i=1,s,t;i<=m;i++)cin>>s>>t,qry[dfn[s]].pb({dfn[t],i});for(int i=1;i<=n;i++){for(optr x:q[i])update(x.l,x.r,x.x);for(optr x:qry[i])ans[x.r]=ask(x.l);}for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';
}
signed main(){//IO();cfast;int _=1;//cin>>_;for(;_;_--)UesugiErii();return 0;
}