Gym - 102040F Path Intersection (树链剖分+线段树)

题意:给出棵树上的k条路径,求这些路径的公共点数量。

将每条路径上的点都打上标记,被标记过k次的点就是公共点了。由于公共点形成的区间是连续的,因此直接在线段树上暴搜即可在$O(logn)$求出一条链上公共点的数量。

怎样找被标记过k次的点呢?可以维护一个区间最大值mx和一个区间最小值mi,如果mx=mi=k说明这一段区间上的点全都为公共点。

清除标记加个线段树区间赋值即可(也可以把标记过的路径一条一条去掉)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=1e4+10,mod=1e9+7;
 5 int hd[N],n,ne,Q,m,fa[N],son[N],siz[N],dep[N],top[N],dfn[N],rnk[N],tot,ka;
 6 int mx[N<<2],mi[N<<2],lza[N<<2],lzs[N<<2];
 7 struct E {int v,nxt;} e[N<<1];
 8 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
 9 void dfs1(int u,int f,int d) {
10     fa[u]=f,son[u]=0,siz[u]=1,dep[u]=d;
11     for(int i=hd[u]; ~i; i=e[i].nxt) {
12         int v=e[i].v;
13         if(v==fa[u])continue;
14         dfs1(v,u,d+1),siz[u]+=siz[v];
15         if(siz[v]>siz[son[u]])son[u]=v;
16     }
17 }
18 void dfs2(int u,int tp) {
19     top[u]=tp,dfn[u]=++tot,rnk[dfn[u]]=u;
20     if(son[u])dfs2(son[u],top[u]);
21     for(int i=hd[u]; ~i; i=e[i].nxt) {
22         int v=e[i].v;
23         if(v==fa[u]||v==son[u])continue;
24         dfs2(v,v);
25     }
26 }
27 #define ls (u<<1)
28 #define rs (u<<1|1)
29 #define mid ((l+r)>>1)
30 void pu(int u) {mx[u]=max(mx[ls],mx[rs]),mi[u]=min(mi[ls],mi[rs]);}
31 void change(int u,int x,int f) {
32     if(f==0)lza[u]=0,lzs[u]=mx[u]=mi[u]=x;
33     else lza[u]+=x,mx[u]+=x,mi[u]+=x;
34 }
35 void pd(int u) {
36     if(~lzs[u])change(ls,lzs[u],0),change(rs,lzs[u],0),lzs[u]=-1;
37     if(lza[u])change(ls,lza[u],1),change(rs,lza[u],1),lza[u]=0;
38 }
39 void upd(int L,int R,int x,int f,int u=1,int l=1,int r=tot) {
40     if(l>=L&&r<=R) {change(u,x,f); return;}
41     if(l>R||r<L)return;
42     pd(u),upd(L,R,x,f,ls,l,mid),upd(L,R,x,f,rs,mid+1,r),pu(u);
43 }
44 int qry(int L,int R,int u=1,int l=1,int r=tot) {
45     if(l>=L&&r<=R&&mx[u]==m&&mi[u]==m)return r-l+1;
46     if(l>R||r<L||mx[u]!=m)return 0;
47     pd(u);
48     return qry(L,R,ls,l,mid)+qry(L,R,rs,mid+1,r);
49 }
50 void upd2(int u,int v) {
51     for(; top[u]!=top[v]; u=fa[top[u]]) {
52         if(dep[top[u]]<dep[top[v]])swap(u,v);
53         upd(dfn[top[u]],dfn[u],1,1);
54     }
55     if(dep[u]<dep[v])swap(u,v);
56     upd(dfn[v],dfn[u],1,1);
57 }
58 int qry2(int u,int v) {
59     int ret=0;
60     for(; top[u]!=top[v]; u=fa[top[u]]) {
61         if(dep[top[u]]<dep[top[v]])swap(u,v);
62         ret+=qry(dfn[top[u]],dfn[u]);
63     }
64     if(dep[u]<dep[v])swap(u,v);
65     ret+=qry(dfn[v],dfn[u]);
66     return ret;
67 }
68 int main() {
69     int T;
70     for(scanf("%d",&T); T--;) {
71         printf("Case %d:\n",++ka);
72         memset(hd,-1,sizeof hd),ne=tot=0;
73         scanf("%d",&n);
74         for(int i=1; i<n; ++i) {
75             int u,v;
76             scanf("%d%d",&u,&v);
77             addedge(u,v);
78             addedge(v,u);
79         }
80         dfs1(1,0,1),dfs2(1,1);
81         scanf("%d",&Q);
82         while(Q--) {
83             upd(1,tot,0,0);
84             scanf("%d",&m);
85             for(int i=0; i<m; ++i) {
86                 int u,v;
87                 scanf("%d%d",&u,&v);
88                 upd2(u,v);
89                 if(i==m-1)printf("%d\n",qry2(u,v));
90             }
91         }
92     }
93 }

 

posted @ 2019-08-12 21:55  jrltx  阅读(277)  评论(0编辑  收藏  举报