樹剖 樹上差分 部落衝突

2021-08-10 03:06:47 字數 1917 閱讀 6385

處理下面三件事,所有的事件都是按照時間順序給出的。

1.(q p q)從第 p 個部落出發的建築工人想知道能否到達第 q 個部落了,你要回答的便是(yes/no),注意大小寫

2.(c p q)第 p 個部落與第 q 個部落開戰了,保證他們一定是相鄰的部落,且目前處於停戰(未開戰)狀態

3.(u x ) 第 x 次發生的戰爭結束了,它將永遠的被載入史冊,不復存在(保證這個訊息不會告訴你多次)

對於30%的資料 1<=n,m<=6000

對於另30%的資料,保證部落之間的地理關係是一條鏈,且 i 與 i + 1 之間有一條道路

對於另30%的資料,1<=n,m<=100000

對於100%的資料,1<=n,m<=300000

一道很裸的樹剖

但是資料太大卡線段樹,用樹狀陣列可以過

用樹狀陣列維護一條鏈上是否有戰爭

這個思想可以樹上差分

樹狀陣列維護sum(i)i到root的戰爭個數

詢問sum(p)+sum(q)-sum(lca(p,q))*2

#include

#include

#include

#define n 300010

#define fr first

#define se second

#define mp(p,q) make_pair(p,q)

using

namespace

std;

pairb[n<<1];

int num,h[n],d[n],fa[n],sz[n],son[n],top[n],tot,dfn[n],n,m,t[n],p,q,cnt,c[n];

char ch;

int rd()

int lb(int x)

void ljb(int p,int q)

int dfs(int x)

return sz[x];

}void dfs(int x)

void ins(int x,int v)

int sum(int x)

bool que(int p,int q)

if(dfn[p]return sum(dfn[p])-sum(dfn[q])?1:0;

}int main()

else

if(ch=='q')

else

}}

#include

#include

#include

#define n 300010

#define fr first

#define se second

#define mp(p,q) make_pair(p,q)

using

namespace

std;

pairb[n<<1];

int num,h[n],d[n],fa[n],sz[n],son[n],top[n],tot,dfn[n],n,m,t[n],p,q,cnt,c[n];

char ch;

int rd()

int lb(int x)

void ljb(int p,int q)

int dfs(int x)

return sz[x];

}void dfs(int x)

void ins(int x,int v)

int sum(int x)

bool que(int p,int q)

if(dfn[p]return sum(dfn[p])-sum(dfn[q])?1:0;

}int main()

else

if(ch=='q')

else

}}

Luogu P3950部落衝突(樹鏈剖分)

題目鏈結 狀態奇差無比,sbt都能錯一遍。不動筆光想沒有想到怎麼做,畫圖之後發現乙個很明顯的性質 那就是兩個開戰的部落,其中乙個是另乙個的父親。所以在兒子那裡加個權值。查詢的時候樹鏈剖分查詢鏈上點權和,減去lca的點權 因為lca那如果有點權,代表的是lca和lca的父親之間的那條邊 include...

P3950 部落衝突(樹鏈剖分)

簡單起見,你就是要處理下面三件事,所有的事件都是按照時間順序給出的。q p q從第 pp 個部落出發的建築工人想知道能否到達第 qq 個部落了,你要回答的便是yes no,注意大小寫。c p q第 pp 個部落與第 qq 個部落開戰了,保證他們一定是相鄰的部落,且目前處於停戰 未開戰 狀態。u x第...

簡單題 最小生成樹, 樹鏈剖分, 樹上差分

將最小生成樹構建出來,將沒加入最小生成樹的邊稱為 虛邊 假設有一條 虛邊 為 u,v u,vu,v,則 u,v u,vu,v 在樹上的路徑上的邊可能被替換,稱路徑上的邊被覆蓋 同上 include define reg register define pb push back intread whi...