poj 3237 樹鏈剖分

2021-07-04 18:27:05 字數 1764 閱讀 5142

對樹有三種操作:

q~  a b  詢問a~b路徑的最大值;

n~  a b  對a~b路徑上的數進行取反操作;(a=-a)

c~  a b  將第a條邊的值改為b;

對於取反操作,記錄區間的最大和最小值和標記k,更新線段即可。

//#pragma comment(linker, "/stack:1024000000,1024000000")

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

#define eps 1e-8

#define pii pair#define inf 0x3f3f3f3f

#define rd(x) scanf("%d",&x)

#define rd2(x,y) scanf("%d%d",&x,&y)

#define ll long long int

#define mod 1000000007

#define maxn 100005

#define maxm 1000005

struct edgeedge[maxn*2];

int head[maxn],tot;

int top[maxn];//v所在重鏈的頂端節點

int fa[maxn];

int deep[maxn];

int num[maxn];//表示以v為根的子樹的節點數

int fp[maxn];//該邊的兒子

int son[maxn];//重兒子

int pos;

int maxx(int a,int b)

int mixx(int a,int b)

}}//第二遍dfs求出top和p

void getpos(int u,int sp)

}struct nodetree[maxn*3];

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

void push_down(int i)

}void push_up(int i)

int query(int i,int l,int r)

void change(int i,int l,int r)

push_down(i);

int mid=(tree[i].l+tree[i].r)>>1;

if(r<=mid) change(i<<1,l,r);

else if(l>mid) change((i<<1)|1,l,r);

else

push_up(i);

}void update(int i,int k,int val)

push_down(i);

int mid=(tree[i].l+tree[i].r)>>1;

if(k<=mid) update(i<<1,k,val);

else update((i<<1)|1,k,val);

push_up(i);

}int findma(int u,int v)

void change(int u,int v)

int t,n,a,b,c;

int e[maxn][3];

int main()

char op[10];

while(scanf("%s",op))

}return 0;

}

POJ 3237(樹鏈剖分)

這道題算是樹鏈剖分的模板題吧 其實也是我過的第一道樹鏈剖分的題目 歷盡千辛萬苦,終於把兩百多行的 敲出來了,ac的一瞬間還是挺爽的。在學會了樹鏈剖分之後,這道題不算很難的了,主要是在區間取反的部分注意一下細節。樹鏈剖分 挺長的,很多地方都是容易寫錯。我也是通過討論區的acmer給出的資料找出一些錯誤...

poj3237 樹鏈剖分

wa了n發,每次取相反數的時候,都需要交換最大值和最小值,這樣才能維護動態的平衡,因為lazy標誌的原因,取相反數,沒有更新到底,所以如果只維護乙個最大值會出問題。include include include const int n 50010 using namespace std struct...

poj 3237 樹鏈剖分 線段樹

題意 給一棵樹,三種操作。將第i條邊的權值改為v,將a到b的路徑上的邊的權值全部取反,求a到b路徑上邊的權值的最大值。思路 明顯的樹鏈剖分,加上線段樹的操作。因為有取反的操作所以每個區間要記錄最大值和最小值。查詢兩點間的路徑時,用求公共祖先的方式去求。include include includec...