poj 3237 Tree(树链剖分)

来源:互联网 发布:不编程的app 编辑:程序博客网 时间:2024/05/16 07:26

Tree
Time Limit: 5000MS Memory Limit: 131072KTotal 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 vNEGATE a bNegate the weight of every edge on the path from a to bQUERY 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

131 2 12 3 2QUERY 1 2CHANGE 1 3QUERY 1 2DONE

Sample Output

13

Source

POJ Monthly--2007.06.03, Lei, Tao

题意:给定一棵树,有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