POJ3237Tree 树链剖分+线段树

Posted CQzhangyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3237Tree 树链剖分+线段树相关的知识,希望对你有一定的参考价值。

【POJ3237】Tree

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N ? 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGE i v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b Find the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N ? 1 lines each contains three integers ab and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3
题解:树剖+线段树裸题,其中取相反数的操作就是把最大值和最小值交换在分别取相反数就好了
#include <stdio.h>
#include <string.h>
#include <iostream>
#define lson x<<1
#define rson x<<1|1
using namespace std;
typedef long long ll;
const int maxn=10010;
int n,cnt,tot;
int sm[maxn<<2],sn[maxn<<2],tag[maxn<<2];
int to[maxn<<1],next[maxn<<1],val[maxn<<1],v[maxn],u[maxn],fa[maxn],head[maxn];
int deep[maxn],size[maxn],son[maxn],p[maxn],top[maxn];
char str[10];
int readin()
{
    int ret=0,sig=1;    char gc;
    while(gc<0||gc>9)    sig=(gc==-)?-1:1,gc=getchar();
    while(gc>=0&&gc<=9)    ret=ret*10+gc-0,gc=getchar();
    return ret*sig;
}
void add(int a,int b,int c)
{
    to[cnt]=b;
    val[cnt]=c;
    next[cnt]=head[a];
    head[a]=cnt++;
}
void dfs1(int x)
{
    size[x]=1;
    for(int i=head[x];i!=-1;i=next[i])
    {
        if(to[i]!=fa[x])
        {
            fa[to[i]]=x;
            u[to[i]]=val[i];
            deep[to[i]]=deep[x]+1;
            dfs1(to[i]);
            size[x]+=size[to[i]];
            if(size[to[i]]>size[son[x]])    son[x]=to[i];
        }
    }
}
void dfs2(int x,int tp)
{
    top[x]=tp;
    p[x]=++tot;
    v[p[x]]=u[x];
    if(son[x])    dfs2(son[x],tp);
    for(int i=head[x];i!=-1;i=next[i])
        if(to[i]!=son[x]&&to[i]!=fa[x])
            dfs2(to[i],to[i]);
}
void pushup(int x)
{
    sm[x]=max(sm[lson],sm[rson]);
    sn[x]=min(sn[lson],sn[rson]);
}
void pushdown(int x)
{
    if(tag[x])
    {
        swap(sm[lson],sn[lson]),swap(sm[rson],sn[rson]);
        sm[lson]=-sm[lson],sn[lson]=-sn[lson],sm[rson]=-sm[rson],sn[rson]=-sn[rson];
        tag[lson]^=1,tag[rson]^=1;
        tag[x]=0;
    }
}
void build(int l,int r,int x)
{
    if(l==r)
    {
        sm[x]=sn[x]=v[l];
        return ;
    }
    int mid=l+r>>1;
    build(l,mid,lson),build(mid+1,r,rson);
    pushup(x);
}
void updata(int l,int r,int x,int a,int b)
{
    if(l==r)
    {
        sm[x]=sn[x]=b;
        return ;
    }
    pushdown(x);
    int mid=l+r>>1;
    if(a<=mid)    updata(l,mid,lson,a,b);
    else    updata(mid+1,r,rson,a,b);
    pushup(x);
}
void upgate(int l,int r,int x,int a,int b)
{
    if(a<=l&&r<=b)
    {
        tag[x]^=1;
        swap(sm[x],sn[x]);
        sm[x]=-sm[x],sn[x]=-sn[x];
        return ;
    }
    pushdown(x);
    int mid=l+r>>1;
    if(b<=mid)    upgate(l,mid,lson,a,b);
    else if(a>mid)    upgate(mid+1,r,rson,a,b);
    else    upgate(l,mid,lson,a,b),upgate(mid+1,r,rson,a,b);
    pushup(x);
}
int query(int l,int r,int x,int a,int b)
{
    if(a<=l&&r<=b)    return sm[x];
    pushdown(x);
    int mid=l+r>>1;
    if(b<=mid)    return query(l,mid,lson,a,b);
    if(a>mid)    return query(mid+1,r,rson,a,b);
    return max(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
}
void change()
{
    int x=readin(),y=readin();
    updata(1,n,1,max(p[to[x*2-2]],p[to[x*2-1]]),y);
}
void fan()
{
    int x=readin(),y=readin();
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]])    swap(x,y);
        upgate(1,n,1,p[top[x]],p[x]);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y])    swap(x,y);
    if(x!=y)    upgate(1,n,1,p[x]+1,p[y]);
}
void getmax()
{
    int x=readin(),y=readin(),ans=1<<31;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]])    swap(x,y);
        ans=max(ans,query(1,n,1,p[top[x]],p[x]));
        x=fa[top[x]];
    }
    if(deep[x]>deep[y])    swap(x,y);
    if(x!=y)    ans=max(ans,query(1,n,1,p[x]+1,p[y]));
    printf("%d\n",ans);
}
void work()
{
    n=readin();
    memset(head,-1,sizeof(head));
    memset(son,0,sizeof(son));
    memset(fa,0,sizeof(fa));
    memset(tag,0,sizeof(tag));
    cnt=tot=0;
    int i,a,b,c;
    for(i=1;i<n;i++)
    {
        a=readin(),b=readin(),c=readin();
        add(a,b,c),add(b,a,c);
    }
    deep[1]=1;
    dfs1(1);
    dfs2(1,1);
    build(1,n,1);
    while(scanf("%s",str))
    {
        switch(str[0])
        {
            case C:change();    break;
            case N:fan();    break;
            case Q:getmax();    break;
            case D:return ;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)    work();
    return 0;
}

 

以上是关于POJ3237Tree 树链剖分+线段树的主要内容,如果未能解决你的问题,请参考以下文章

POJ3237Tree 树链剖分+线段树

(树链剖分+线段树)POJ - 3237 Tree

POJ3237-Tree (树链剖分,线段树区间更新+点更新+区间查询)

POJ 3237 Tree(树链剖分)

POJ 3723 Tree(树链剖分)

POJ 3237 /// 树链剖分 线段树区间修改(*-1)