有這麼一道題:給出一顆樹,以及點權,支援兩種操作
單點修改
求兩點之間的最短路上的所有點權和
資料範圍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/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的...