括號序與線段樹

2021-09-24 05:10:20 字數 1658 閱讀 2406

有這麼一道題:給出一顆樹,以及點權,支援兩種操作

單點修改

求兩點之間的最短路上的所有點權和

資料範圍1e5

我們可以dfs序建出一顆線段樹,並且加一些括號,其中l[u]對應左括號,r[u]對應右括號,左括號為1,右括號為-1,那麼求某點u到節點1的路上經過的節點的權值和就是求區間[1,l[u]]上的和。

對於單點修改,將u的點權改為w,就是線段樹單點修改,將l[u]=w,r[u]=-w;

路徑求u,v之間的點權和就是 ( 1 , l[u] )+( 1 , l[v] )-2*( 1 , [l[lca(u,v)]] )+單點 l[lca(u,v)] 的值。

沒找到題測試,**可能寫的有問題2333。

#includeusing namespace std;

typedef long long ll;

const int maxn=1e5+7;

const int maxm=1e5+7;

struct edgeedge[maxm];

int w[maxn];

int head[maxn],top;

void init()

void add(int u,int v,int w)

bool vis[maxn];

int dfn;

int l[maxn],r[maxn];

int b[maxn<<1];

int dep[maxn];

int fa[maxn][20];

void dfs(int u)

r[u]=++dfn;

b[r[u]]=-w[u];

}int lca(int x,int y)

int n;

int sum[maxn<<2|1];

void pushup(int k)

void build(int l,int r,int k)

int mid=(l+r)>>1;

build(l,mid,k<<1);

build(mid+1,r,k<<1|1);

pushup(k);

}void updata(int l,int r,int k,int id,int v)

int mid=(l+r)>>1;

if(id<=mid) updata(l,mid,k<<1,id,v);

else updata(mid+1,r,k<<1|1,id,v);

pushup(k);

}int myfind(int l,int r,int l,int r,int k)

int myfindid(int l,int r,int k,int id)

char s[9];

int main()

dfs(1);

n<<=1;

//for(int i=1;i<=n;++i) cout

int m;

scanf("%d",&m);

while(m--)

else

}return 0;}/*

81 2 3 4 5 6 7 8

1 21 3

2 42 5

2 63 8

4 7100

a 4 8

*/

Assign the task(dfs序 線段樹)

hdoj 3974 題意 有一家公司有n個員工 從1到n 公司裡每個員工都有乙個直接的老闆 除了整個公司的領導 如果你是某人的直接老闆,那個人就是你的下屬,他的所有下屬也都是你的下屬。如果你是沒有人的老闆,那麼你就沒有下屬,沒有直接老闆的員工就是整個公司的領導,也就是說n個員工構成了一棵樹。公司通常...

Assign the task(dfs序 線段樹)

題目傳送門 assign the task 給你一棵樹,共n個結點,每個結點具有乙個顏色,可以對結點進行染色和查詢 共n 1條邊,分n 1行分別包含兩個整數u和v,表示v是u的父節點 然後有m次操作 若為染色操作則輸入 t x k 若為查詢操作則輸入 c x 首先可以用dfs序將無根樹區間化,即可以...

dfs序 線段樹

傳送門 現有一棵樹,有以下操作 1.節點x及其所有子孫顏色都變更為k。2.要求你回答節點x的顏色。初始所有點都沒有染色。input 第一行乙個整數t t 10 表示樣例組數。對於每個測試樣例 第一行乙個整數n n 5e4 表示樹的節點個數。接下來n行,每行兩個整數u,v 1 u,v n 表示樹中u的...