POJ3237 Tree 樹鏈剖分

2021-08-07 15:13:45 字數 2275 閱讀 2783

題意:給定一棵樹,有3種操作,1.修改某條邊,2.給兩個點間路徑上的邊取相反數,3.求兩個點間路徑上的邊權的最大值

思路:樹鏈剖分,求區間最大值,又能取反,那麼線段樹維護乙個最大值和最小值,取反的時候,一段區間的最大值取反 賦給 最小值,最小值取反 賦給 最大值。同時,需要乙個laze標記。

#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

typedef pairpii;

#define lson(x) 2*x

#define rson(x) 2*x+1

const int maxn = 1e5+5;

struct edge

edge[maxn*2];

struct ed

e[maxn];

int head[maxn],tot,cnt;

int root,size[maxn],dep[maxn],fa[maxn],son[maxn];

int top[maxn],id[maxn],val[maxn];

/*size -> 以x為根節點子樹的大小 dep -> 深度

fa -> 父節點 son -> 重兒子

top -> x所在重鏈的頂端節點

*/struct data

node[maxn*4];

void init()

void add(int x,int y)

int dfs1(int x,int pre,int d)

} return size[x];

}void dfs2(int x,int pre)

}void pushup(int cnt)

void build(int x,int y, int cnt)

int mid = (x+y) / 2;

build(x,mid,lson(cnt));

build(mid+1,y,rson(cnt));

pushup(cnt);

}void down(int cnt)

void up(int x,int y,int cnt,int val)

down(cnt);

int fa = 2*cnt;

if(x <= node[fa].r)

fa++;

if(y >= node[fa].l)

pushup(cnt);

}void neg(int x,int y,int cnt)

down(cnt);

int fa = 2*cnt;

if(x <= node[fa].r)

fa++;

if(y >= node[fa].l)

pushup(cnt);

}int fid(int x,int y,int cnt)

int fa = 2*cnt;

if(x <= node[fa].r)

fa++;

if(y >= node[fa].l)

return res;

}int qurey(int u,int v)

if(u == v) return ans;

if(dep[u] > dep[v])

swap(u,v);

ans = max(ans,fid(id[son[u]],id[v],1));

return ans;//邊權,存的都是點的父邊,最上面的點用son[u]

}void ne(int u,int v)

if(u == v) return;

if(dep[u] > dep[v])

swap(u,v);

neg(id[son[u]],id[v],1);

}int main()

root = (n+1) / 2;

dfs1(root,root,1);

dfs2(root,root);

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

build(1,cnt,1);

char op[15];

while(scanf("%s",op)!=eof && op[0] != 'd')

else if(op[0] == 'n')

else

}}}

poj3237 Tree 樹鏈剖分

這個題是spoj的改版 是在原來的題意上增加了區間取反操作 所以只需要在spoj375的基礎上再線段樹上增加乙個取反標誌 同時在維護乙個區間最小值 因為在區間取反了以後 區間的最大值就是區間原來的最小值 嗯 就這樣就可以了 include include include using namespac...

POJ 3237 Tree 樹鏈剖分

題意 給出一棵樹,每條邊有乙個權值。下面有3種操作 分析 因為是線段樹成段取反操作,可以先打個neg標記,表示這段區間的數是否取反。再維護區間最大值和最小值,取反之後,新區間的最大值是原來最小值的相反數,新區間最小值是原來最大值的相反數。include include include using n...

POJ3237 Tree 樹鏈剖分 邊權

傳送門 n個點的,n 1條邊 修改單邊邊權 將a b的邊權取反 查詢a b邊權最大值 修改邊權就查詢點的深度大的點,用大的點去存這條邊的邊權,其餘的就和點權的是一樣的了 取反操作用線段樹維護,區間最大值取反就是區間最小值,區間最小值取反就是區間最大值 所以維護兩顆線段樹即可,lazy標記表示覆蓋單邊...