codeforces 852I Dating(DFS序,LCA,莫队)
来源:互联网 发布:linux如何安装win7 编辑:程序博客网 时间:2024/06/10 13:02
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.
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).
For each of the q questions output a single number, the answer to the citizens question.
71 0 0 1 0 1 09 2 9 2 2 9 92 61 24 26 53 67 421 37 5
23
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;}
- codeforces 852I Dating(DFS序,LCA,莫队)
- CodeForces 208E Blood Cousins(树剖求lca + dfs序)
- poj3417Network(LCA+dfs)
- hdu5452(LCA+DFS)
- dfs(tarjan)求lca
- BZOJ 3991(dfs序 + LCA 公式推导)
- [HDU 5296] Annoying problem (DFS序性质+LCA)
- [BZOJ4539][Hnoi2016]树(dfs序+主席树+lca)
- [BZOJ3589]动态树(树链剖分+dfs序+lca)
- [BZOJ3881][Coci2015]Divljak(AC自动机+dfs序+lca+bit)
- [BZOJ3991][SDOI2015]寻宝游戏(dfs序+lca+set)
- NOIP2015运输计划(二分+dfs序+lca)
- HDU 6203 ping ping ping (LCA+DFS序)
- Paths 升级(DFS序+线段树+LCA+树形DP)
- Codeforces Gym 100338I TV Show DFS
- [LCA][dfs序]BZOJ 2819: Nim
- [BZOJ2819] Nim && dfs序 + 树状数组 + LCA
- HDU 5296 Annoying problem dfs序+lca
- Exam1_2
- 批处理中for循环的自增自减问题
- 【安全牛学习笔记】AIRRACK-NG(二)
- bzoj 3111: [Zjoi2013]蚂蚁寻路(DP)
- Redis 集合(Set)介绍与基本操作
- codeforces 852I Dating(DFS序,LCA,莫队)
- HDU 5533(计算几何+暴力)
- 第十二章 与Spring集成(三) Shiro权限注解
- C++学习札记
- Unity_设计模式_状态模式_05
- HDU4866-Shooting
- RabbitMQ原理
- 顺序表应用7:最大子段和之分治递归法
- Windows平台异常处理 开发中何时利用异常处理模块