休息了兩天,今天開始做樹鏈剖分,除了模板長以外,還是挺好理解的。就只是線段樹+剖分獨特的函式,然後樹鏈剖分所用的陣列有點多,沒了。其中需要注意的乙個點是「鏈」(路徑)不一定是從根節點到葉子節點的,輕兒子這個點它也有重兒子啊啊啊。
再說這個題,單點更新,區間取相反數,區間求最大值。
/***********
poj3237
2015.1.23
2504k 657ms c++ 6396b
***********/
#include #include#include#includeusing namespace std;
const int maxn=101010+5;
const int maxm=maxn+maxn;
struct edgenode
edges[maxm];
int head[maxn],edge;
inline void init()
inline void addedge(int u,int v,int w)
int que[maxn],son[maxn],idx[maxn],dep[maxn],siz[maxn],belong[maxn],fa[maxn],top[maxn],len[maxn],sump[maxn],seg[maxn],wei[maxn];
int l,r,ans,cnt,n;
bool vis[maxn];
char cmd[22];
void split()}}
if(p==-1)
else
vis[u]=true;
}}const int inf=0x3f3f3f3f;
struct segmenttree
; tree tree[maxn*4];
void push_down(int root)
}tree[root].neg=0;
}void push_up(int root)
void build(int root,int l,int r)
int mid=(l+r)/2;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
push_up(root);
}void update(int root,int pos,int val)
push_down(root);
int mid=(tree[root].l+tree[root].r)/2;
if(pos<=mid)update(root<<1,pos,val);
else update(root<<1|1,pos,val);
push_up(root);
}int query(int root,int l,int r)
void nega(int root,int l,int r)
push_down(root);
int mid=(tree[root].l+tree[root].r)/2;
if(l<=mid) nega(root<<1,l,r);
if(r>mid) nega(root<<1|1,l,r);
push_up(root);
}void debug(int root)
}tr;
int find(int va,int vb)
void gao(int va,int vb)
int d[maxn][3];
int main()
{ // freopen("cin.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{init();
scanf("%d",&n);
for(int i=1;i
poj3237 Tree 樹鏈剖分
這個題是spoj的改版 是在原來的題意上增加了區間取反操作 所以只需要在spoj375的基礎上再線段樹上增加乙個取反標誌 同時在維護乙個區間最小值 因為在區間取反了以後 區間的最大值就是區間原來的最小值 嗯 就這樣就可以了 include include include using namespac...
POJ3237 Tree 樹鏈剖分
題意 給定一棵樹,有3種操作,1.修改某條邊,2.給兩個點間路徑上的邊取相反數,3.求兩個點間路徑上的邊權的最大值 思路 樹鏈剖分,求區間最大值,又能取反,那麼線段樹維護乙個最大值和最小值,取反的時候,一段區間的最大值取反 賦給 最小值,最小值取反 賦給 最大值。同時,需要乙個laze標記。incl...
POJ 3237 Tree 樹鏈剖分
題意 給出一棵樹,每條邊有乙個權值。下面有3種操作 分析 因為是線段樹成段取反操作,可以先打個neg標記,表示這段區間的數是否取反。再維護區間最大值和最小值,取反之後,新區間的最大值是原來最小值的相反數,新區間最小值是原來最大值的相反數。include include include using n...