【NOIP2017提高组A组模拟8.17】行程的交集
2017-08-17 22:23
441 查看
Description
豪哥生活在一个n个点的树形城市里面,每一天都要走来走去。虽然走的是比较的多,但是豪哥在这个城市里面的朋友并不是很多。当某一天,猴哥给他展现了一下大佬风范之后,豪哥决定要获得一些交往机会来提升交往能力。豪哥现在已经物色上了一条友,打算和它(豪哥并不让吃瓜群众知道性别)交往。豪哥现在spy了一下这个人的所有行程起点和终点,豪哥打算从终点开始走到起点与其相遇。但是豪哥是想找话题的,他想知道以前有多少次行程和此次行程是有交集的,这样豪哥就可以搭上话了。这个路径与之前路径的有交集数量作为豪哥此次的交往机会。
但是豪哥急着要做交往准备,所以算什么交往机会的小事情就交给你了。
分析
两条路径相交的情况就是:1、这条路径的lca在另一条路径上。
2、某条路径穿过这条路径的lca。
我们用两个树状数组来维护,用dfs序。
对于第一种情况,我们维护这个点到根节点的路径上面有多少个lca,然后相减就能得到答案。
对于第二种情况,我们在两个节点上面打一个+1的标记,在lca上面打一个-2的标记,这样就将整条链都+1了。
code
#include<queue> #include<cstdio> #include<iostream> #include<algorithm> #include <cstring> #include <string.h> #include <cmath> #include <math.h> #define ll long long #define N 200003 #define db double #define P putchar #define G getchar #define mo 1000000007 using namespace std; char ch; void read(int &n) { n=0; ch=G(); while((ch<'0' || ch>'9') && ch!='-')ch=G(); ll w=1; if(ch=='-')w=-1,ch=G(); while('0'<=ch && ch<='9')n=n*10+ch-'0',ch=G(); n*=w; } void write(ll x) { if(x>9) write(x/10); P(x%10+'0'); } int n,m,x,y,ans,p,q; int nxt[N*2],a[N*2],last ,tot; int dfn ,la ,f [18],deep ,id; int z[2] ,pass ; int low(int x) { return x & (-x); } int find(int x,int y) { int s=0; //y=0 经过某个点,y=1 某个点到根有多少个lca for(int i=x;i;i=i-low(i)) s+=z[y][i]; return s; } void change(int x,int y,int s) { for(int i=x;i<=n;i=i+low(i)) z[y][i]+=s; } void ins(int x,int y) { nxt[++tot]=last[x]; a[tot]=y; last[x]=tot; } void dfs(int x) { dfn[x]=++id; for(int i=last[x];i;i=nxt[i]) if(!deep[a[i]]) { deep[a[i]]=deep[x]+1; f[a[i]][0]=x; dfs(a[i]); } la[x]=id; } int lca(int x,int y) { if(deep[y]>deep[x])swap(x,y); for(int i=17;i>=0;i--) if(deep[f[x][i]]>=deep[y])x=f[x][i]; if(x==y)return x; for(int i=17;i>=0;i--) if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0]; } int main() { read(n); for(int i=1;i<n;i++) read(x),read(y),ins(x,y),ins(y,x); deep[1]=1; dfs(1); for(int j=1;j<17;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1]; read(m); for(int i=1;i<=m;i++) { read(x);read(y); p=lca(x,y); ans=pass[p]+find(la[p],0)-find(dfn[p]-1,0); ans+=find(dfn[x],1)-find(dfn[p],1)*2+find(dfn[y],1); change(dfn[p],1,1);change(la[p]+1,1,-1); change(dfn[x],0,1);change(dfn[p],0,-2); change(dfn[y],0,1); pass[p]++; write(ans),P('\n'); } }
相关文章推荐
- jzoj5290 【NOIP2017提高组A组模拟8.17】行程的交集 (树上路径交,dfs序+树状数组维护姿势)
- 【jzoj5290】【NOIP2017提高组A组模拟8.17】【行程的交集】
- 【NOIP2017提高组模拟12.18】B
- 【NOIP2017提高A组模拟10.8】Lost My Music
- JZOJ.5289【NOIP2017模拟8.17】偷笑
- JZOJ5347【NOIP2017提高A组模拟9.5】遥远的金字塔 斜率优化 DP
- 【NOIP2017提高A组模拟9.7】计数题
- JZOJ5358【NOIP2017提高A组模拟9.12】BBQ
- 【NOIP2017提高A组模拟10.7】Adore
- 【NOIP2017提高组模拟12.18】C
- JZOJ.5288【NOIP2017模拟8.17】球场大佬
- 【NOIP2017提高A组模拟8.25】影子
- jzoj5363【NOIP2017提高A组模拟9.14】生命之树 trie+启发式合并
- 【NOIP2017提高A组模拟7.13】第K小数
- 【NOIP2017提高A组模拟10.7】Adore
- 【NOIP2017提高组模拟12.10】神炎皇
- 【NOIP2017提高组模拟12.10】幻魔皇
- JZOJ 4711 Binary【NOIP2016提高A组模拟8.17】
- [jzoj4711]【NOIP2016提高A组模拟8.17】Binary