poj3237 Tree 樹鏈剖分

2021-07-04 03:22:04 字數 1712 閱讀 2882

這個題是spoj的改版

是在原來的題意上增加了區間取反操作

所以只需要在spoj375的基礎上再線段樹上增加乙個取反標誌

同時在維護乙個區間最小值

因為在區間取反了以後 區間的最大值就是區間原來的最小值

嗯 就這樣就可以了

#include #include #include using namespace std;

struct nodeedge[20001];

struct node1a[10001];

int cnt;

int dep[10001],num[10001],fa[10001],head[10001],siz[10001],son[10001],topfa[10001],id[10001];

void add(int x,int y)

void dfs1(int x,int f,int d)

void swap(int &x,int &y)

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

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

build(l,mid,ls);

build(mid+1,r,rs);

t[x].max=max(t[ls].max,t[rs].max);

t[x].min=min(t[ls].min,t[rs].min);

}void updata(int x,int ls,int rs)

else

if(t[rs].flag)

else

}void change(int l,int v,int x)

if(t[x].flag)

int mid=(t[x].l+t[x].r)>>1;

if(l<=mid) change(l,v,ls);

if(l>mid) change(l,v,rs);

updata(x,ls,rs);

}void change_flag(int l,int r,int x)

int mid=(t[x].l+t[x].r)>>1;

if(t[x].flag)

if(r<=mid) change_flag(l,r,ls);

else if(l>mid) change_flag(l,r,rs);

else

updata(x,ls,rs);

}int tree_query(int l,int r,int x)

int mid=(t[x].l+t[x].r)>>1;

int ans;

if(t[x].flag)

if(mid>=r) ans=tree_query(l,r,ls);

else if(middep[y]) swap(x,y);

if(topfa[x]==topfa[y])

if(dep[topfa[y]]>dep[topfa[x]]) swap(x,y);

change_flag(id[topfa[x]],id[x],1);

flag(fa[topfa[x]],y);

}int query(int x,int y){

if(x==y) return -1234567890;

if(dep[x]>dep[y]) swap(x,y);

if(topfa[x]==topfa[y]) return tree_query(id[x]+1,id[y],1);

if(dep[topfa[x]]

POJ3237 Tree 樹鏈剖分

題意 給定一棵樹,有3種操作,1.修改某條邊,2.給兩個點間路徑上的邊取相反數,3.求兩個點間路徑上的邊權的最大值 思路 樹鏈剖分,求區間最大值,又能取反,那麼線段樹維護乙個最大值和最小值,取反的時候,一段區間的最大值取反 賦給 最小值,最小值取反 賦給 最大值。同時,需要乙個laze標記。incl...

POJ 3237 Tree 樹鏈剖分

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

POJ3237 Tree 樹鏈剖分 邊權

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