對樹有三種操作:
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...