2018 icpc Regional Dhaka F Path Intersection
阿新 • • 發佈:2020-10-20
題意:求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:\n",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\n",res); } } return 0; }