2018.10.05 NOIP模擬 相遇(dfs序+lca)
阿新 • • 發佈:2018-12-13
描述
豪哥生活在一個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
考慮到兩條路徑相交的條件: 設兩條路徑為。 則要麼路徑的在上。 要麼路徑的在上。 因此我們維護兩棵樹。 分別支援路徑加,單點查值和單調加,路徑查值。 這個直接樹狀陣列維護就行了。 程式碼:
#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;
}