1. 程式人生 > >2018.10.05 NOIP模擬 相遇(dfs序+lca)

2018.10.05 NOIP模擬 相遇(dfs序+lca)

描述

豪哥生活在一個n個點的樹形城市裡面,每一天都要走來走去。雖然走的是比較的多,但是豪哥在這個城市裡面的朋友並不是很多。 當某一天,猴哥給他展現了一下大佬風範之後,豪哥決定要獲得一些交往機會來提升交往能力。豪哥現在已經物色上了一條友,打算和它(豪哥並不讓吃瓜群眾知道性別)交往。豪哥現在spy了一下這個人的所有行程起點和終點,豪哥打算從終點開始走到起點與其相遇。但是豪哥是想找話題的,他想知道以前有多少次行程和此次行程是有交集的,這樣豪哥就可以搭上話了。這個路徑與之前路徑的有交集數量作為豪哥此次的交往機會。 但是豪哥急著要做交往準備,所以算什麼交往機會的小事情就交給你了。

輸入

第一行一個正整數n表示節點個數。接下來n-1行,每行兩個正整數分別是u,v表示節點u和v之間有連邊。接下來一行一個 正整數m表示路徑個數。然後有m行,每行兩個正整數分別是u,v分別表示u到v之間有一條路徑

輸出

輸出共m行,每行一個整數,第i行表示豪哥在這條路徑上獲得的交往機會。

樣例輸入

5 1 2 1 3 3 4 3 5 4 4 5 4 2 1 3 1 2

樣例輸出

0 1 2 2

提示

【資料範圍與約定】 對於20%的資料n,m≤2000 對於另外20%的資料n,m≤50000 對於另外10%的資料n,m≤200000保證樹形結構是一條鏈 對於另外50%的資料n,m≤200000

考慮到兩條路徑相交的條件: 設兩條路徑為a,ba,b。 則要麼aa路徑的lcalcabb上。 要麼bb路徑的lcalcaaa上。 因此我們維護兩棵樹。 分別支援路徑加,單點查值和單調加,路徑查值。 這個直接樹狀陣列維護就行了。 程式碼:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define N 200005
using namespace std;
int n,m,siz[N],hson[N],top[N],fa[N],dep[N],num[N],num_[N],first[N],lcnt[N],tot=0,cnt=0,bit1[N],bit2[N];
struct edge{int v,next;}e[N<<1];
inline void
dfs1(int p){ siz[p]=1; for(int i=first[p];i;i=e[i].next){ int v=e[i].v; if(v==fa[p])continue; fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v]; if(siz[v]>siz[hson[p]])hson[p]=v; } } inline void dfs2(int p,int tp){ top[p]=tp,num[p]=++tot; if(!hson[p])return; dfs2(hson[p],tp); for(int i=first[p];i;i=e[i].next){ int v=e[i].v; if(v!=fa[p]&&v!=hson[p])dfs2(v,v); } num_[p]=tot; } inline int lca(int x,int y){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); x=fa[top[x]]; } return dep[x]<dep[y]?x:y; } inline int read(){ int ans=0; char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); return ans; } inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;} inline int lowbit(int x){return x&-x;} inline void update(int*T,int x,int v){for(int i=x;i<=n;i+=lowbit(i))T[i]+=v;} inline int query(int*T,int x){int ret=0;for(int i=x;i;i-=lowbit(i))ret+=T[i];return ret;} int main(){ int size=40<<20; __asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size)); n=read(); for(int i=1;i<n;++i){ int u=read(),v=read(); add(u,v),add(v,u); } dfs1(1),dfs2(1,1); m=read(); while(m--){ int a=read(),b=read(),t=lca(a,b); printf("%d\n",lcnt[t]+query(bit1,num_[t])-query(bit1,num[t]-1)+query(bit2,num[a])+query(bit2,num[b])-2*query(bit2,num[t])); ++lcnt[t],update(bit1,num[a],1),update(bit1,num[b],1),update(bit1,num[t],-2),update(bit2,num[t],1),update(bit2,num_[t]+1,-1); } exit(0); return 0; }