codeforces 852I Dating(DFS序,LCA,莫队)

来源:互联网 发布:linux如何安装win7 编辑:程序博客网 时间:2024/06/10 13:02
I. Dating
time limit per test
2 seconds
memory limit per test
64 megabytes
input
standard input
output
standard output

This story is happening in a town named BubbleLand. There are n houses in BubbleLand. In each of these n houses lives a boy or a girl. People there really love numbers and everyone has their favorite number f. That means that the boy or girl that lives in the i-th house has favorite number equal to fi.

The houses are numerated with numbers 1 to n.

The houses are connected with n - 1 bidirectional roads and you can travel from any house to any other house in the town. There is exactly one path between every pair of houses.

A new dating had agency opened their offices in this mysterious town and the citizens were very excited. They immediately sent qquestions to the agency and each question was of the following format:

  • a b — asking how many ways are there to choose a couple (boy and girl) that have the same favorite number and live in one of the houses on the unique path from house a to house b.

Help the dating agency to answer the questions and grow their business.

Input

The first line contains an integer n (1 ≤ n ≤ 105), the number of houses in the town.

The second line contains n integers, where the i-th number is 1 if a boy lives in the i-th house or 0 if a girl lives in i-th house.

The third line contains n integers, where the i-th number represents the favorite number fi (1 ≤ fi ≤ 109) of the girl or boy that lives in the i-th house.

The next n - 1 lines contain information about the roads and the i-th line contains two integers ai and bi (1 ≤ ai, bi ≤ n) which means that there exists road between those two houses. It is guaranteed that it's possible to reach any house from any other.

The following line contains an integer q (1 ≤ q ≤ 105), the number of queries.

Each of the following q lines represents a question and consists of two integers a and b (1 ≤ a, b ≤ n).

Output

For each of the q questions output a single number, the answer to the citizens question.

Example
input
71 0 0 1 0 1 09 2 9 2 2 9 92 61 24 26 53 67 421 37 5
output
23
Note

In the first question from house 1 to house 3, the potential couples are (1, 3) and (6, 3).

In the second question from house 7 to house 5, the potential couples are (7, 6)(4, 2) and (4, 5).

题意:给你一个N个点,N-1条边的图,每个点有一个男孩或者女孩,每个人都有一个数字,数字相同的才可能在一起,有Q个询问,每次求a,b之间的最短路径上的人可能组成的情侣的数量

题解:根据题意可知这是一棵树,最短路径就是树上的路径,对于a,b有两种情况:一种a或者b是LCA,那么答案就是从DFS序中的in[a]到in[b]求;

另一种情况则是从out[a]到in[b]中求,这里对于LCA要特殊处理,因为out[a]到in[b]不会包含LCA

然后是用莫队求答案:对于所求的区间,如果是路径上的点,那出现的次数为1,否则为2次,所以只需要记录下这个点的出现次数就好了,亦或一下就好了,这是一个树上的莫队,不会的可以自己手模一下,然后就是LCA特殊判一下就好了


代码:

#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<math.h>#define N 100005using namespace std;typedef long long ll;int a[N],b[N],d1[N],d2[N],time,d[N],f[N][20],ji[N],rev[N*2],mark[N];ll ans[N],c[2][N];vector<int>v[N];struct node{    int x,y,lca,id;}query[N];bool cmp(node& a,node &b){    if(a.x/time==b.x/time)return a.y<b.y;    return a.x<b.x;}void dfs(int p,int fa){    d1[p]=++time;    rev[time]=p;    d[p]=d[fa]+1;    f[p][0]=fa;    for(int i=1;i<20;i++)        f[p][i]=f[f[p][i-1]][i-1];    int m=v[p].size();    for(int i=0;i<m;i++)    {        int to=v[p][i];        if(to==fa)continue;        dfs(to,p);    }    d2[p]=++time;    rev[time]=p;}int lca(int x,int y){    if(d[x]<d[y])swap(x,y);    for(int i=19;i>=0;i--)        if(d[f[x][i]]>=d[y])x=f[x][i];    if(x==y)return x;    for(int i=19;i>=0;i--)        if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];    return f[x][0];}ll sum=0;void update(int x){    int p=rev[x];    sum-=c[0][a[p]]*c[1][a[p]];    c[ji[p]][a[p]]+=(mark[p]?-1:1);    mark[p]^=1;    sum+=c[0][a[p]]*c[1][a[p]];}int main (){    int n,q,x,y;    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&ji[i]);    for(int i=1;i<=n;i++){        scanf("%d",&a[i]);        b[i]=a[i];    }    sort(b+1,b+n+1);    int num=unique(b+1,b+n+1)-b;    for(int i=1;i<=n;i++)        a[i]=lower_bound(b+1,b+num,a[i])-b;    for(int i=1;i<n;i++){        scanf("%d%d",&x,&y);        v[x].push_back(y);        v[y].push_back(x);    }    dfs(1,0);    scanf("%d",&q);    time=sqrt(time);    for(int i=0;i<q;i++)    {        scanf("%d%d",&x,&y);        int fa=lca(x,y);        if(d1[x]>d1[y])swap(x,y);        if(x==fa)query[i]=node{d1[x],d1[y],0,i};        else query[i]=node{d2[x],d1[y],d1[fa],i};    }    sort(query,query+q,cmp);    int l=0,r=0;    for(int i=0;i<q;i++)    {        while(r+1<=query[i].y)update(++r);        while(r>query[i].y)update(r--);        while(l-1>=query[i].x)update(--l);        while(l<query[i].x)update(l++);        if(query[i].lca)update(query[i].lca);        ans[query[i].id]=sum;        if(query[i].lca)update(query[i].lca);    }    for(int i=0;i<q;i++)        printf("%lld\n",ans[i]);    return 0;}