poj 3237 Tree(树链剖分)

Tree
Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 3405 Accepted: 953

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 vChange the weight of the ith edge to v
NEGATE a bNegate the weight of every edge on the path from a to b
QUERY a bFind 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

Source


题意:给定一棵树,有3个操作:1、修改某条边权值。2、询问2个节点间最大边权。3、把2个节点间所有边权取相反数

题解:树链剖分。。线段树部分需要lazy。。还挺好写的,不过要注意一下lazy值的维护


#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 100008;
struct edge{
    int to,next;
}e[maxn<<1];
struct segment{
    int ma,mi,lazy;
}tree[maxn<<2];
int head[maxn],d[maxn][3];
int dep[maxn],w[maxn],fa[maxn];
int top[maxn],son[maxn],siz[maxn];
int n,all,root,t,a,b,c,z;
char s[18];
void add(int x,int y)
{
    e[++all].to=y;
    e[all].next=head[x];
    head[x]=all;
}
void dfs(int x)
{
    siz[x]=1;  son[x]=0;
    for(int i=head[x];i!=-1;i=e[i].next)
    {
        if(e[i].to==fa[x]) continue;
        fa[e[i].to]=x;
        dep[e[i].to]=dep[x]+1;
        dfs(e[i].to);
        if(siz[e[i].to]>siz[son[x]]) son[x]=e[i].to;
        siz[x]+=siz[e[i].to];
    }
}
void build_tree(int x,int tp)
{
    w[x]=++z; top[x]=tp;
    if(son[x]!=0) build_tree(son[x],top[x]);
    for(int i=head[x];i!=-1;i=e[i].next)
    {
        if(e[i].to!=son[x]&&e[i].to!=fa[x])
            build_tree(e[i].to,e[i].to);
    }
}
void build_segment_tree(int pos,int l,int r)
{
    int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1;
    tree[pos].lazy=0;
    tree[pos].ma=-0xffffff;
    tree[pos].mi=0xffffff;
    if(l==r) return;
    build_segment_tree(ls,l,mid);
    build_segment_tree(rs,mid+1,r);
}
void make_negate(int pos)
{
    tree[pos].ma=-tree[pos].ma;
    tree[pos].mi=-tree[pos].mi;
    swap(tree[pos].ma,tree[pos].mi);
}
void push_down(int pos)
{
    int ls=pos<<1,rs=pos<<1|1;
    tree[pos].lazy=0;
    tree[ls].lazy^=1;
    tree[rs].lazy^=1;
    make_negate(ls);
    make_negate(rs);
}
void push_up(int pos)
{
    tree[pos].ma=max(tree[pos<<1].ma,tree[pos<<1|1].ma);
    tree[pos].mi=min(tree[pos<<1].mi,tree[pos<<1|1].mi);
}
void update(int pos,int l,int r,int loc,int val)
{
    int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1;
    if(loc>r||loc<l) return;
    if(l==r){ tree[pos].mi=tree[pos].ma=val; return; }
    if(tree[pos].lazy) push_down(pos);
    update(ls,l,mid,loc,val);
    update(rs,mid+1,r,loc,val);
    push_up(pos);
}
int maxi(int pos,int l,int r,int ltemp,int rtemp)
{
    int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1;
    if(l>rtemp||ltemp>r) return -0xffffff;
    if(ltemp<=l&&r<=rtemp) return tree[pos].ma;
    if(tree[pos].lazy) push_down(pos);
    return max(maxi(ls,l,mid,ltemp,rtemp)
               ,maxi(rs,mid+1,r,ltemp,rtemp));
}
int myfind(int va,int vb)
{
    int f1=top[va],f2=top[vb],tmp=-0xffffff;
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2]){ swap(f1,f2); swap(va,vb); }
        tmp=max(tmp,maxi(1,1,z,w[f1],w[va]));
        va=fa[f1];  f1=top[va];
    }
    if(va==vb) return tmp;
    if(dep[va]>dep[vb]) swap(va,vb);
    return max(tmp,maxi(1,1,z,w[son[va]],w[vb]));
}
void update_negate(int pos,int l,int r,int ltemp,int rtemp)
{
    int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1;
    if(l>rtemp||ltemp>r) return;
    //printf("cc   %d   %d    %d   %d\n",l,r,ltemp,rtemp);
    if(ltemp<=l&&r<=rtemp)
    {
        tree[pos].lazy^=1;
        make_negate(pos);
        return;
    }
    if(tree[pos].lazy) push_down(pos);
    update_negate(ls,l,mid,ltemp,rtemp);
    update_negate(rs,mid+1,r,ltemp,rtemp);
    push_up(pos);
}
void mynegate(int va,int vb)
{
    int f1=top[va],f2=top[vb];
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2]){ swap(f1,f2); swap(va,vb); }
        update_negate(1,1,z,w[f1],w[va]);
        va=fa[f1];  f1=top[va];
    }
    if(va==vb) return;
    if(dep[va]>dep[vb]) swap(va,vb);
    update_negate(1,1,z,w[son[va]],w[vb]);
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(head,-1,sizeof(head));
        memset(tree,0,sizeof(tree));
        memset(siz,0,sizeof(siz));
        scanf("%d",&n);
        root=(n+1)/2;
        fa[root]=dep[root]=z=all=0;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            d[i][0]=a,d[i][1]=b,d[i][2]=c;
            add(a,b),add(b,a);
        }
        dfs(root);
        build_tree(root,root);
        build_segment_tree(1,1,z);
        for(int i=1;i<n;i++)
        {
            if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]);
            update(1,1,z,w[d[i][1]],d[i][2]);
        }
        while(scanf("%s",s),s[0]!='D')
        {
            scanf("%d%d",&a,&b);
            if(s[0]=='Q') printf("%d\n",myfind(a,b));
            else if(s[0]=='N') mynegate(a,b);
            else update(1,1,z,w[d[a][1]],b);
        }
    }

    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值