Journey CodeForces - 1336F[data structures divide and conquer graphs trees]

In the wilds far beyond lies the Land of Sacredness, which can be viewed as a tree  — connected undirected graph consisting of nn nodes and n1n−1 edges. The nodes are numbered from 11 to nn.

There are mm travelers attracted by its prosperity and beauty. Thereupon, they set off their journey on this land. The ii-th traveler will travel along the shortest path from sisi to titi. In doing so, they will go through all edges in the shortest path from sisi to titi, which is unique in the tree.

During their journey, the travelers will acquaint themselves with the others. Some may even become friends. To be specific, the ii-th traveler and the jj-th traveler will become friends if and only if there are at least kk edges that both the ii-th traveler and the jj-th traveler will go through.

Your task is to find out the number of pairs of travelers (i,j)(i,j) satisfying the following conditions:

  • 1i<jm1≤i<j≤m.
  • the ii-th traveler and the jj-th traveler will become friends.

Input

The first line contains three integers nn, mm and kk (2n,m1.51052≤n,m≤1.5⋅105, 1kn1≤k≤n).

Each of the next n1n−1 lines contains two integers uu and vv (1u,vn1≤u,v≤n), denoting there is an edge between uu and vv.

The ii-th line of the next mm lines contains two integers sisi and titi (1si,tin1≤si,ti≤n, sitisi≠ti), denoting the starting point and the destination of ii-th traveler.

It is guaranteed that the given edges form a tree.

Output

The only line contains a single integer  — the number of pairs of travelers satisfying the given conditions.

Examples

Input
8 4 1
1 7
1 2
2 5
4 6
6 3
6 2
6 8
7 8
3 8
2 6
4 1
Output
4
Input
10 4 2
3 10
9 3
4 9
4 6
8 2
1 7
2 1
4 5
6 7
7 1
8 7
9 2
10 3
Output
1
Input
13 8 3
7 6
9 11
5 6
11 3
9 7
2 12
4 3
1 2
5 8
6 13
5 10
3 1
10 4
10 11
8 11
4 9
2 5
3 5
7 3
8 10
Output
14

Note

In the first example there are 44 pairs satisfying the given requirements: (1,2)(1,2), (1,3)(1,3), (1,4)(1,4), (3,4)(3,4).

  • The 11-st traveler and the 22-nd traveler both go through the edge 686−8.
  • The 11-st traveler and the 33-rd traveler both go through the edge 262−6.
  • The 11-st traveler and the 44-th traveler both go through the edge 121−2 and 262−6.
  • The 33-rd traveler and the 44-th traveler both go through the edge 262−6.

tutorial:

First, let's choose an arbitrary root for the tree. Then for all pairs of paths, their LCA (lowest common ancestor) can be either different or the same.

Then, let's calculate the answer of pairs with different LCAs. In this case, if the intersection is not empty, it will be a vertical path as in the graph below.

Here path G-H and path E-F intersects at path B-G

We can process all paths in decreasing order of the depth of their LCA. When processing a path p we calculate the number of paths q, where q is processed before p, and the edge-intersection of p and q is at least k. To do this we can plus one to the subtree of the nodes on the path k edges away from the LCA (node C and D for path G-H in the graph above), then we can query the value at the endpoints of the path (node E and F for path E-F). We can maintain this easily with BIT (binary indexed tree, or Fenwick tree).

Next, we calculate pairs with the same LCA. This case is harder.

For each node u we calculate the number of pairs with the LCA u.

For a pair of path (x_1,y_1) and (x_2, y_2), there are still two cases we need to handle.

In the first case (the left one in the graph above), where the intervals [dfn_{x_1},dfn_{y_1}] (dfn_x is the index of x in the DFS order) and [dfn_{x_2},dfn_{y_2}] have no intersection. In this case the intersection of two paths is a vertical path where (y_1,u) and (x_2,u) intersects. This can be solved similarly to the case of different LCAs.

In the next case (the right one in the graph above), an intersection of the two intervals exists. The intersection of two paths may cross over node u.

For all paths (x,y) (assume that dfn_x < dfn_y) with the LCA u. We can build a virtual-tree over all x of the paths, and on node x we store the value of y. Let's do a dfs on the virtual-tree. On each node a we calculate pairs (x_1,y_1),(x_2,y_2) that \operatorname{LCA}(x_1,x_2) = a. For x_1 , let's go from a to y_1 for k edges, assume the node we reached is b, all legal y_2 should be in the subtree of b.

We can use a segment tree on the DFS-order to maintain all ys in the subtree and merge them with the small-to-large trick, meanwhile, iterate over all x_1 in the smaller segment tree, count the valid y_2's in the larger segment tree.

In fact, you can use HLD (heavy-light decomposition) instead of virtual-tree, which seems to be easier to implement.

The overall complexity of this solution is O(m \log^2 m + n\log n).

solution:

#include <bits/stdc++.h>
#define maxn 200005
int n,m,k,u[maxn],v[maxn],ch[maxn<<6][2]={0},sum[maxn<<6]={0},pt[maxn],head[maxn]={0},tail=0,cnt=0,root[maxn]={0},
anc[maxn][19]={0},son[maxn]={0},depth[maxn]={0},dfn[maxn],size[maxn],idx=0;
long long ans=0;
std::vector<int>in[maxn],vec[maxn];
struct edge {
    int v,next;
}edges[maxn<<1];
void add_edge(int u,int v){
    edges[++tail].v=v;
    edges[tail].next=head[u];
    head[u]=tail;
}
namespace BIT {
    int sum[maxn<<2]={0};
    void add(int p,int x) {if (p==0) return;while (p<=n) {sum[p]+=x;p+=p&-p;}}
    int query(int p) {int ans=0;while (p>0) {ans+=sum[p];p-=p&-p;}return ans;}
    void Add(int l,int r){add(l,1);add(r+1,-1);}
}
void update(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]];}
int insert(int rt,int l,int r,int p){
    if (!rt) rt=++cnt;
    if (l==r) {sum[rt]++;return rt;}
    int mid=(l+r)>>1;
    if (p<=mid) ch[rt][0]=insert(ch[rt][0],l,mid,p);
    else ch[rt][1]=insert(ch[rt][1],mid+1,r,p);
    update(rt);
    return rt;
} int merge(int u,int v){
    if (!u||!v)return u+v;
    ch[u][0]=merge(ch[u][0],ch[v][0]);
    ch[u][1]=merge(ch[u][1],ch[v][1]);
    sum[u]=sum[u]+sum[v];return u;
} int query(int rt,int L,int R,int l,int r){
    if (l>R||r<L)return 0;
    if (l<=L&&R<=r){return sum[rt];}
    return query(ch[rt][0],L,(L+R)>>1,l,r)+query(ch[rt][1],((L+R)>>1)+1,R,l,r);
}

void dfs1(int u,int f){
    anc[u][0]=f;depth[u]=depth[f]+1;size[u]=1;
    for (int i=1;i<=18;++i)anc[u][i]=anc[anc[u][i-1]][i-1];
    for (int i=head[u];i;i=edges[i].next){
        int v=edges[i].v;
        if (v==f) continue;
        dfs1(v,u);size[u]+=size[v];
        if (size[v]>size[son[u]])son[u]=v;
    }
} void dfsn(int u){
    dfn[u]=++idx;
    for (int i=head[u];i;i=edges[i].next){
        int v=edges[i].v;
        if (v==son[u]||v==anc[u][0])continue;
        dfsn(v);
    }if (son[u]) dfsn(son[u]);
}

int lift(int u,int x){
    for (int i=18;i>=0;i--)if (x>=(1<<i)) {u=anc[u][i];x-=(1<<i);}
    return u;
}

int lca(int u,int v){
    if (depth[u]<depth[v])std::swap(u,v);
    for (int i=18;i>=0;i--)if (depth[anc[u][i]]>=depth[v])u=anc[u][i];
    if (u==v)return u;
    for (int i=18;i>=0;i--)if (anc[u][i]!=anc[v][i]){u=anc[u][i];v=anc[v][i];}
    return anc[u][0];
} 

void dfs3(int x,int rt){
    pt[x]=x;root[x]=0;
    for (int i=0;i<in[x].size();++i) {
        int d=in[x][i];
        int rd=std::max(0,k-(depth[u[d]]-depth[rt]));
        if (depth[v[d]]-depth[rt]>=rd){
            int l=lift(v[d],depth[v[d]]-depth[rt]-rd);
            ans+=query(root[x],1,n,dfn[l],dfn[l]+size[l]-1);
        }root[x]=insert(root[x],1,n,dfn[v[d]]);
    }for (int i=head[x];i;i=edges[i].next){
        int t=edges[i].v;
        if (t==anc[x][0]||(rt==x&&t==son[x])) continue;
        dfs3(t,rt);
        if (in[pt[x]].size()<in[pt[t]].size()){
            std::swap(pt[x],pt[t]);
            std::swap(root[x],root[t]);
        }while (!in[pt[t]].empty()){
            int d=in[pt[t]][in[pt[t]].size()-1];in[pt[t]].pop_back();
            int rd=std::max(0,k-(depth[x]-depth[rt]));
            if (depth[v[d]]-depth[rt]>=rd) {
                int l=lift(v[d],(depth[v[d]]-depth[rt]-rd));
                ans+=query(root[x],1,n,dfn[l],dfn[l]+size[l]-1);
            }in[pt[x]].push_back(d);
        }root[x]=merge(root[x],root[t]);
    }
}

void dfs2(int x){
    int len=vec[x].size();
    for (int i=head[x];i;i=edges[i].next)if (edges[i].v!=anc[x][0])dfs2(edges[i].v);
    for (int i=0;i<len;++i)ans+=BIT::query(dfn[v[vec[x][i]]]);
    for (int i=0;i<len;++i){
        int j=vec[x][i];
        if (depth[v[j]]-depth[x]>=k) {
            int l=lift(v[j],depth[v[j]]-depth[x]-k);
            BIT::Add(dfn[l],dfn[l]+size[l]-1);
        }
    }for (int i=0;i<len;++i){ans+=BIT::query(dfn[u[vec[x][i]]]);in[u[vec[x][i]]].push_back(vec[x][i]);}
    dfs3(x,x);
    while (!in[pt[x]].empty())in[pt[x]].pop_back();
    for (int i=0;i<len;++i){
        int j=vec[x][i];
        if (depth[u[j]]-depth[x]>=k) {
            int l=lift(u[j],depth[u[j]]-depth[x]-k);
            BIT::Add(dfn[l],dfn[l]+size[l]-1);
        }
    }
}
    
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<n;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        add_edge(u,v);
        add_edge(v,u);
    }dfs1(1,0);dfsn(1);
    for (int i=1;i<=m;++i){
        scanf("%d%d",&u[i],&v[i]);
        if (dfn[u[i]]>dfn[v[i]]) std::swap(u[i],v[i]);
        int l=lca(u[i],v[i]);
        vec[l].push_back(i);
    } dfs2(1);
    std::cout<<ans;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xxxsans/p/12716805.html