原題:
題意:給出一棵樹,n節點,每次詢問給兩對葉子,求這兩對葉子產生路徑的交集
解析:
找被走過兩次的點->走被走過兩次的所有lca,lca所構成的那一段長度就是點的數量
顯然,目標線段的端點一定是這些葉子節點的某個lca
找到所有lca,放入set
統計哪些lca被走過兩次
怎麼判斷走過幾次:一對葉子(x1,x2)與它的節點l1,假設某個點在x1到l1之間或x2到l2之間,則在路徑上
怎麼判斷在x1和l1之間:lca(x1,p)==p&&lca(p,l1)==l1
對於走過兩次的點,求出組成路徑的長度
怎麼求路徑:首先是所有點的lca,作為root,刪除除了最底下點以外的所有點
怎麼刪除:if(lca(p1,p2)==p2)erase(p2)
#include
using namespace std;
#define maxn 500005
int head[maxn<<1]
,fa[maxn][25
],vis[maxn]
,cnt,dep[maxn]
,dis[maxn]
;struct node
e[maxn<<1]
;void
add(
int x,
int y)
void
bfs()}
}int
lca(
int x,
int y)
set<
int>st;
map<
int,
int>mp;
vector<
int>fin;
intmain()
for(set<
int>
::iterator it=st.
begin()
;it!=st.
end(
);it++
)int ans=0;
for(map<
int,
int>
::iterator it=mp.
begin()
;it!=mp.
end(
);it++)if
(fin.
size()
==0)if
(fin.
size()
==1)int l3,deep=
1e9;
for(
int i=
0;isize()
;i++
)while
(fin.
size()
>2)
}}if(
lca(fin[0]
,fin[1]
)==fin[0]
) fin.
erase
(fin.
begin()
);elseif(
lca(fin[0]
,fin[1]
)==fin[1]
) fin.
erase
(fin.
begin()
+1);
for(
int i=
0;isize()
;i++
) ans+
=(dep[fin[i]
]-dep[l3]);
ans++
;printf
("%d\n"
,ans);}
return0;
}
一條分兩條
一條拆成兩條 統計當前客戶經理和客戶關係,上年底客戶經理和客戶關係 如果客戶經理和客戶關係跨越這兩個時間段,那麼一條分成兩條 with basic t as 客戶和客戶經理關係表 select 123 cust no,a am no,20091231 start dt 29991231 end dt...
兩條序列聯配
一 序列聯配的概念 序列聯配又叫序列比對,根據特定的計分規則,通過演算法對多條蛋白質序列或dna序列進行比對,找出最優匹配和最大相似度匹配。通過聯配可以得到乙個相似度比對值 根據計分規則算 這個值反映了他們的相似度 同源性 進化上的親緣關係。序列聯配分為區域性聯配和全域性聯配兩種。全域性聯配就是對整...
牛客 兩條斜線
題意 斜率為 1的兩條直線最多經過幾個點。題解 設斜率為1的直線為y x b1,斜率為 1的直線為y x b2,b1 y x,b2 y x,b1或b2相同則點在這兩條直線上。所以問題變成了最多有幾個點的b1或b2相同,那麼列舉b1b2即可。include using namespace std ma...