Tree - POJ 3237 树链刨分

来源:互联网 发布:java web get post 编辑:程序博客网 时间:2024/06/06 03:59

Tree
Time Limit: 5000MS Memory Limit: 131072KTotal Submissions: 6101 Accepted: 1671

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

题意:给你一棵树,边上有权值,更新操作有将一个路径上的值取反,和更改一个点的值。查询操作查询两个点之间路径的最大边值。

思路:树链刨分,就是线段树敲起来复杂了些。

AC代码如下:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;struct node1{    int u,v,w;}arr[10010];struct node2{    int u,v,w,next;}edge[20010];struct node3{    int l,r,maxn,minn,lazy;}tree[40010];int T,t,n,m,tot,tot2,Head[10010],INF=1e9;int siz[10010],son[10010],depth[10010],fa[10010],top[10010],p[10010];int W[10010];char s[10];void dfs1(int u){    int i,j,k,v;    siz[u]=1;    son[u]=0;    for(i=Head[u];i!=-1;i=edge[i].next)    {        v=edge[i].v;        if(v==fa[u])          continue;        depth[v]=depth[u]+1;        fa[v]=u;        dfs1(v);        if(siz[v]>siz[son[u]])          son[u]=v;        siz[u]+=siz[v];    }}void dfs2(int u,int f){    int i,j,k,v;    p[u]=++tot2;    top[u]=f;    if(son[u]!=0)      dfs2(son[u],f);    for(i=Head[u];i!=-1;i=edge[i].next)    {        v=edge[i].v;        if(v==fa[u] || v==son[u])          continue;        dfs2(v,v);    }}void add(int u,int v,int w){    edge[tot].u=u;    edge[tot].v=v;    edge[tot].w=w;    edge[tot].next=Head[u];    Head[u]=tot++;}void up(int tr){    tree[tr].maxn=max(tree[tr*2].maxn,tree[tr*2+1].maxn);    tree[tr].minn=min(tree[tr*2].minn,tree[tr*2+1].minn);}void op(int tr){    tree[tr].maxn=-tree[tr].maxn;    tree[tr].minn=-tree[tr].minn;    swap(tree[tr].maxn,tree[tr].minn);}void down(int tr){    int minn,maxn;    if(tree[tr].lazy)    {        tree[tr].lazy=0;        tree[tr*2].lazy=(tree[tr*2].lazy+1)%2;        tree[tr*2+1].lazy=(tree[tr*2+1].lazy+1)%2;        op(tr*2);        op(tr*2+1);    }}void build(int l,int r,int tr){    tree[tr].l=l;    tree[tr].r=r;    tree[tr].lazy=0;    if(l==r)    {        tree[tr].maxn=tree[tr].minn=W[l];        return;    }    int mi=(l+r)/2;    build(l,mi,tr*2);    build(mi+1,r,tr*2+1);    up(tr);}void update1(int l,int r,int tr){    if(tree[tr].l==l && tree[tr].r==r)    {        tree[tr].lazy=(tree[tr].lazy+1)%2;        op(tr);        return;    }    down(tr);    int mi=(tree[tr].l+tree[tr].r)/2;    if(r<=mi)      update1(l,r,tr*2);    else if(l>mi)      update1(l,r,tr*2+1);    else    {        update1(l,mi,tr*2);        update1(mi+1,r,tr*2+1);    }    up(tr);}void update2(int id,int tr,int num){    if(tree[tr].l==tree[tr].r)    {        tree[tr].maxn=tree[tr].minn=num;        return;    }    down(tr);    int mi=(tree[tr].l+tree[tr].r)/2;    if(id<=mi)      update2(id,tr*2,num);    else      update2(id,tr*2+1,num);    up(tr);}int query(int l,int r,int tr){    if(tree[tr].l==l && tree[tr].r==r)      return tree[tr].maxn;    down(tr);    int mi=(tree[tr].l+tree[tr].r)/2;    if(r<=mi)      return query(l,r,tr*2);    else if(l>mi)      return query(l,r,tr*2+1);    else      return max(query(l,mi,tr*2),query(mi+1,r,tr*2+1));}int solve(int u,int v,int type){    int f1=top[u],f2=top[v],k,maxn=-INF;    while(f1!=f2)    {        if(depth[f1]<depth[f2])        {            swap(f1,f2);            swap(u,v);        }        if(type==1)          update1(p[f1],p[u],1);        else          maxn=max(maxn,query(p[f1],p[u],1));        u=fa[f1];        f1=top[u];    }    if(u==v)      return maxn;    if(depth[u]>depth[v])      swap(u,v);    if(type==1)      update1(p[son[u]],p[v],1);    else      maxn=max(maxn,query(p[son[u]],p[v],1));    return maxn;}int main(){    int i,j,k,u,v,w,pos,ans;    scanf("%d",&T);    for(t=1;t<=T;t++)    {        scanf("%d",&n);        tot=tot2=0;        memset(Head,-1,sizeof(Head));        for(i=1;i<n;i++)        {            scanf("%d%d%d",&u,&v,&w);            arr[i].u=u;            arr[i].v=v;            arr[i].w=w;            add(u,v,w);            add(v,u,w);        }        depth[1]=1;        dfs1(1);        dfs2(1,1);        for(i=1;i<n;i++)        {            if(arr[i].v==fa[arr[i].u])              swap(arr[i].v,arr[i].u);            W[p[arr[i].v]]=arr[i].w;        }        build(1,tot2,1);        while(true)        {            scanf("%s",s+1);            if(s[1]=='C')            {                scanf("%d%d",&i,&w);                update2(p[arr[i].v],1,w);            }            else if(s[1]=='N')            {                scanf("%d%d",&u,&v);                solve(u,v,1);            }            else if(s[1]=='Q')            {                scanf("%d%d",&u,&v);                ans=solve(u,v,2);                printf("%d\n",ans);            }            else              break;        }    }}



0 0
原创粉丝点击