★★★☆ 輸入檔案:maintaintree.in
輸出檔案:maintaintree.out
簡單對比
時間限制:5 s 記憶體限制:128 mb
給你由n個結點組成的樹。樹的節點被編號為1到n,邊被編號為1到n-1。每一條邊有乙個權值。然後你要在樹上執行一系列指令。指令可以是如下三種之一:
change i v:將第i條邊的權值改成v。
negate a b:將點a到點b路徑上所有邊的權值變成其相反數。
query a b:找出點a到點b路徑上各邊的最大權值。
輸入檔案的第一行有乙個整數n(n<=10000)。
接下來n-1行每行有三個整數a,b,c,代表點a和點b之間有一條權值為c的邊。這些邊按照其編號從小到大給出。
接下來是若干條指令(不超過10^5條),都按照上面所說的格式。
輸入檔案的最後一行是"done".
對每個「query」指令,輸出一行,即路徑上各邊的最大權值。
1 2 1
2 3 2
query 1 2
change 1 3
query 1 2
done
這裡的輸入輸出格式和poj上原題略有不同。
poj 3237 tree
難點在於取相反數操作
記錄下最大值和最小值,有取相反數操作時,就把兩個值變成相反數,再交換兩數的值就ok,然後給這個區間打上標記(線段樹的lazy標記),以後訪問或更改值時記得下傳標記就好。
#include #include#include
#include
using
namespace
std;
const
int maxn = 100010
;struct
edgeedge[maxn*2
];int
head[maxn],tot;
int top[maxn];//
top[v]表示v所在的重鏈的頂端節點
int fa[maxn]; //
父親節點
int deep[maxn];//
深度 int num[maxn];//
num[v]表示以v為根的子樹的節點數
int p[maxn];//
int fp[maxn];//
和p陣列相反
int son[maxn];//
重兒子
intpos;
void
init()
void addedge(int u,int
v)void dfs1(int u,int v,intd)}
void dfs2(int u,intv)}
//線段樹
struct
nodetr[maxn*3
];void build(int i,int l,int
r)void push_up(int
i)void push_down(inti)}
void update(int i,int k,int val)
push_down(i);
int mid = (tr[i].l + tr[i].r)/2
;
if(k <= mid)update(i<<1
,k,val);
else update((i<<1)|1
,k,val);
push_up(i);}
void ne_update(int i,int l,int
r) push_down(i);
int mid=(tr[i].l+tr[i].r)>>1
;
if(r<=mid)ne_update(i<<1
,l,r);
else
if(l>mid)ne_update((i<<1)|1
,l,r);
else ne_update(i<<1,l,mid),ne_update((i<<1)|1,mid+1
,r);
tr[i].min=min(tr[i<<1].min,tr[(i<<1)|1
].min);
tr[i].max=max(tr[i<<1].max,tr[(i<<1)|1
].max);
}int query(int i,int l,int r)
int findmax(int u,int v)
tmp = max(tmp,query(1
,p[f1],p[u]));
u = fa[f1]; f1 =top[u];
}if(u == v)return
tmp;
if(deep[u] >deep[v]) swap(u,v);
return max(tmp,query(1
,p[son[u]],p[v]));
}void negate(int u,int
v)
if(u==v)return
;
if(deep[u]>deep[v])swap(u,v);
ne_update(
1,p[son[u]],p[v]);
return;}
int e[maxn][3
];int
main()
dfs1(
0,1,0
); dfs2(
1,1);
build(
1,0,pos-1
);
for(int i=0;i1;i++)
char ch[10
];
intu,v;
while(1
) }
return0;
}
POJ3237 樹的維護
給你由n個結點組成的樹。樹的節點被編號為1到n,邊被編號為1到n 1。每一條邊有乙個權值。然後你要在樹上執行一系列指令。指令可以是如下三種之一 change i v 將第i條邊的權值改成v。negate a b 將點a到點b路徑上所有邊的權值變成其相反數。query a b 找出點a到點b路徑上各邊...
poj 3237 樹鏈剖分
對樹有三種操作 q a b 詢問a b路徑的最大值 n a b 對a b路徑上的數進行取反操作 a a c a b 將第a條邊的值改為b 對於取反操作,記錄區間的最大和最小值和標記k,更新線段即可。pragma comment linker,stack 1024000000,1024000000 i...
POJ 3237(樹鏈剖分)
這道題算是樹鏈剖分的模板題吧 其實也是我過的第一道樹鏈剖分的題目 歷盡千辛萬苦,終於把兩百多行的 敲出來了,ac的一瞬間還是挺爽的。在學會了樹鏈剖分之後,這道題不算很難的了,主要是在區間取反的部分注意一下細節。樹鏈剖分 挺長的,很多地方都是容易寫錯。我也是通過討論區的acmer給出的資料找出一些錯誤...