emm,這很noip...
寫這個的原因是今天考試乙個sb差分樹題居然槓了個樹剖上去,殺雞用了牛刀。
而且不止一次了...總是想不到子樹和這種差分,淦
anyway,簡單寫寫吧。
三重封裝
轉化後的問題都能用dfs序+樹狀陣列解決。(在上文**中,樹狀陣列用bit
封裝,st, ed
是dfs序)
本質:在序列上,字首和、字尾和均能解決這兩個問題。
而之所以在樹上這兩種形式求解的問題出現不同,是因為與序列相比,樹是上小下大的。
這道題綜合的考察了兩種差分,成功把我幹翻(
[出處不明] 相遇 or 行程的交集
description簡要題意:給你一棵樹,然後按順序輸入若干條路徑。問每次輸入路徑時該路徑與前面已經輸入的多少條路徑有交集。豪哥生活在乙個n個點的樹形城市裡面,每一天都要走來走去。雖然走的是比較的多,但是豪哥在這個城市裡面的朋友並不是很多。
當某一天,猴哥給他展現了一下大佬風範之後,豪哥決定要獲得一些交往機會來提公升交往能力。豪哥現在已經物色上了一條友,打算和它(豪哥並不讓吃瓜群眾知道性別)交往。豪哥現在spy了一下這個人的所有行程起點和終點,豪哥打算從終點開始走到起點與其相遇。但是豪哥是想找話題的,他想知道以前有多少次行程和此次行程是有交集的,這樣豪哥就可以搭上話了。這個路徑與之前路徑的有交集數量作為豪哥此次的交往機會。
但是豪哥急著要做交往準備,所以算什麼交往機會的小事情就交給你了。
input
第一行乙個正整數n表示節點個數。
接下來n-1行,每行兩個正整數分別是u,v表示節點u和v之間有連邊。
接下來一行乙個 正整數m表示路徑個數。
然後有m行,每行兩個正整數分別是u,v分別表示u到v之間有一條路徑。
output
輸出共m行,每行乙個整數,第i行表示豪哥在這條路徑上獲得的交往機會。
sample input
sample output5
1 21 3
3 43 5
44 5
4 21 3
1 2
hint012
2
【資料範圍與約定】
對於20%的資料n,m≤2000
對於另外20%的資料n,m≤50000
對於另外10%的資料n,m≤200000,保證樹形結構是一條鏈
對於另外50%的資料n,m≤200000
主要要想到把兩條樹上路徑有交集轉換為其中某條路徑的lca被另一條路徑所覆蓋。
於是對於當前輸入的路徑,分當前路徑覆蓋了多少個之前路徑的lca和當前路徑的lca被之前多少個路徑覆蓋討論即可。前者是單點修改&鏈查詢,後者是鏈修改&單點查詢,按前文的方法做就可以了。
注意特判lca重疊的情況,見**。
#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
typedef vectorvector;
typedef vector::iterator vecit;
ll rd()
while(c>='0'&&c<='9') ans=ans*10+c-'0',c=getchar();
if(fh) ans=-ans;
return ans;
}ll lowbit(ll x)
const ll ptn=2e5+5;
class bit
bit(ll n)
void add(ll p,ll w)
ll query(ll p)
};ll n;
vector edge[ptn];
ll fa[ptn],dep[ptn],sz[ptn],son[ptn];
ll st[ptn],ed[ptn];ll dn;
void dfs1(ll u,ll father,ll depth)
ed[u]=++dn;
}ll tp[ptn];
void dfs2(ll u,ll toop)
}ll lca(ll u,ll v){
while(tp[u]!=tp[v]){
if(dep[tp[u]]2020/10/24
樹上差分的兩種實現形式
簡單理解樹上差分 點,邊 關於樹上差分,我在這推薦一道題目poj 3417 題目翻譯 樹上差分用來解決點的覆蓋或者邊的覆蓋的問題,需分別運用點的差分或者邊的差分。先從例題入手 給定點數為n,邊數為n 1的樹 無向邊且無重邊 先有m條連線a,b的非樹邊,求每條 樹邊 被 非樹邊 覆蓋了多少次?邊的差分...
C C 的兩種多型形式
1 2 test.cpp4 5 created by mac on 15 8 11.6 7 8 include9 include10 using namespace std 11class person 基類person12 25person person 26 person person stri...
include的兩種指令形式
在程式設計過程中不在意的細節 搬運於c程式設計 include include stdio.h include使用尖括號的形式時,編譯系統從存放c編譯系統的子目錄中去找所要包含的檔案如 stdio.h 這稱為 標準方式 若使用 include指令是為了使用系統庫函式,因而要包含系統提供的相應標頭檔案...