题意:求Q次树上路径交。
题解:树链剖分之后,对于每一条路径,暴力的往上跳,并且用线段树维护一下个数,最终我们需要线段树中最大值和个数。复杂度O(nlog^2n),码量巨大。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
#define fi first
#define se second
#define MP make_pair
#define lson (nd<<1)
#define rson (nd<<1|1)
const int N = 100005;
int tag[N<<2], mn[N<<2], mx[N<<2];
int son[N], sz[N], top[N], fa[N], dep[N];
int head[N], to[N<<1], Next[N<<1], tol;
int L[N], id[N], dfn;
int n;
PII st[N*25];
int tot;
void addAdge(int u, int v){
Next[++tol]=head[u];to[tol]=v;head[u]=tol;
Next[++tol]=head[v];to[tol]=u;head[v]=tol;
}
void dfs1(int u){
sz[u]=1;
for(int e=head[u];e;e=Next[e]){
int v=to[e];
if(v==fa[u])continue;
fa[v]=u;
dep[v]=dep[u]+1;
dfs1(v);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}
void dfs2(int u){
L[u]=++dfn;id[dfn]=u;
if(son[u])top[son[u]]=top[u],dfs2(son[u]);
for(int e=head[u];e;e=Next[e]){
int v=to[e];
if(v==fa[u]||v==son[u])continue;
top[v]=v;
dfs2(v);
}
}
int LCA(int u, int v){
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]){
u=fa[top[u]];
}else{
v=fa[top[v]];
}
}
if(dep[u]<dep[v])return u;
else return v;
}
void getSeg(int u, int v){
while(top[u]!=top[v]){
st[++tot]=MP(L[top[u]],L[u]);
u=fa[top[u]];
}
st[++tot]=MP(L[v],L[u]);
}
void pushUp(int nd){
mx[nd]=max(mx[lson],mx[rson]);
mn[nd]=min(mn[lson],mn[rson]);
}
void pushDown(int nd){
if(tag[nd]){
tag[lson]+=tag[nd];
tag[rson]+=tag[nd];
mx[lson]+=tag[nd];
mx[rson]+=tag[nd];
mn[lson]+=tag[nd];
mn[rson]+=tag[nd];
tag[nd]=0;
}
}
void modify(int nd, int l, int r, int L, int R, int v){
if(L>r||R<l)return;
if(L<=l&&r<=R){
mx[nd]+=v;
mn[nd]+=v;
tag[nd]+=v;
return;
}
int mid=l+r>>1;
pushDown(nd);
if(L<=mid){
modify(lson,l,mid,L,R,v);
}
if(mid+1<=R){
modify(rson,mid+1,r,L,R,v);
}
pushUp(nd);
}
int query(int nd, int l, int r, int MX){
if(mx[nd]!=MX){
return 0;
}
if(mx[nd]==mn[nd]){
return r-l+1;
}
int mid=l+r>>1;
pushDown(nd);
return query(lson,l,mid,MX)+query(rson,mid+1,r,MX);
}
int main(){
int T;scanf("%d",&T);
int kase=1;
while(T--){
memset(head, 0, sizeof head);
memset(son, 0, sizeof son);/*¿Óµã*/
tol=dfn=0;
scanf("%d",&n);
for(int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
addAdge(u,v);
}
dep[1]=1;
top[1]=1;
dfs1(1);
dfs2(1);
int q;
scanf("%d",&q);
printf("Case %d:
",kase++);
for(int iter=1;iter<=q;++iter){
int K;scanf("%d",&K);
tot=0;
vector<int> rt;
for(int iter1=1;iter1<=K;++iter1){
int u, v;
scanf("%d%d",&u,&v);
int lca=LCA(u,v);
getSeg(u,lca);
getSeg(v,lca);
rt.push_back(L[lca]);
}
for(int i=1;i<=tot;++i){
modify(1,1,n,st[i].fi,st[i].se,1);
}
for(auto& nd:rt){
modify(1,1,n,nd,nd,-1);
}
int res=query(1,1,n,K);
for(int i=1;i<=tot;++i){
modify(1,1,n,st[i].fi, st[i].se,-1);
}
for(auto& nd:rt){
modify(1,1,n,nd,nd,1);
}
printf("%d
",res);
}
}
return 0;
}