树链剖分-链的剖分(线段树维护边权值的更新)

来源:互联网 发布:3d合值九宫计算法 编辑:程序博客网 时间:2024/06/07 11:50

poj3237

Tree
Time Limit: 5000MS Memory Limit: 131072KTotal Submissions: 3629 Accepted: 1017

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 bwith 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

题意:给出一颗树以及边权值,对边权有三种操作:(1)把第i条边的权值改成v;(2)把<u,v>路径上的边权值改为原来的相反数;(3)输出<u,v>路径上的最大权值;

程序:

#include"stdio.h"#include"string.h"#include"iostream"#include"map"#include"string"#include"queue"#include"stdlib.h"#include"math.h"#define M 11009#define eps 1e-10#define inf 1000000000#define mod 1000000000#define INF 1000000000using namespace std;struct node{    int u,v,w,next;}edge[M*2];int t,head[M];int son[M];//记录重链中某点的儿子节点,子叶节点的儿子为-1;int fa[M];//记录每个节点的父节点;int num[M];//记录以该节点为根的子树中有多少个节点;int top[M];//记录某条重链中所有节点的最初节点编号;int p[M];//记录某个节点的编号(对原来的节点重新编号)int fp[M];//记录某编号的节点对应的原来的节点编号;int deep[M];//记录某个节点在树中的深度;int a[M];//记录编过号的节点与其父节点之间的边的边权值;维护的线段树是n-1个点int pos;int Max;void init(){    t=pos=0;    memset(head,-1,sizeof(head));    memset(son,-1,sizeof(son));}void add(int u,int v){    edge[t].u=u;    edge[t].v=v;    edge[t].next=head[u];    head[u]=t++;}void dfs(int u,int f,int d){    deep[u]=d;    num[u]=1;    fa[u]=f;    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].v;        if(v!=f)        {            dfs(v,u,d+1);            num[u]+=num[v];            if(son[u]==-1||num[son[u]]<num[v])                son[u]=v;        }    }}void getpos(int u,int sp){    top[u]=sp;    p[u]=pos++;    fp[p[u]]=u;    if(son[u]==-1)return;    getpos(son[u],sp);    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].v;        if(v!=fa[u]&&v!=son[u])            getpos(v,v);    }}//以上是求重链//***************************以下是线段树操作****************************//struct Node{    int l,r,flag,maxi,mini;}tree[M*4];void pushup(int i){    tree[i].maxi=max(tree[i*2].maxi,tree[i*2+1].maxi);    tree[i].mini=min(tree[i*2].mini,tree[i*2+1].mini);}void pushdown(int i)//lazy操作{    if(tree[i].l==tree[i].r)return;    if(tree[i].flag)    {        tree[i*2].maxi=-tree[i*2].maxi;        tree[i*2].mini=-tree[i*2].mini;        swap(tree[i*2].maxi,tree[i*2].mini);        tree[i*2].flag^=1;        tree[i*2+1].maxi=-tree[i*2+1].maxi;        tree[i*2+1].mini=-tree[i*2+1].mini;        swap(tree[i*2+1].maxi,tree[i*2+1].mini);        tree[i*2+1].flag^=1;        tree[i].flag=0;    }}void make(int l,int r,int i)//建立线段树{    tree[i].l=l;    tree[i].r=r;    tree[i].flag=0;    if(tree[i].l==tree[i].r)    {        tree[i].maxi=tree[i].mini=a[tree[i].l];        return;    }    int mid=(l+r)>>1;    make(l,mid,i*2);    make(mid+1,r,i*2+1);    pushup(i);}void change(int p,int q,int i)//单点更新{    if(tree[i].l==p&&tree[i].r==p)    {        tree[i].maxi=tree[i].mini=q;        tree[i].flag=0;        return;    }    pushdown(i);    int mid=(tree[i].l+tree[i].r)>>1;    if(p<=mid)change(p,q,i*2);    else change(p,q,i*2+1);    pushup(i);}void negval(int l,int r,int i)//区间修改为相反数{    if(tree[i].l==l&&tree[i].r==r)    {        tree[i].maxi=-tree[i].maxi;        tree[i].mini=-tree[i].mini;        swap(tree[i].maxi,tree[i].mini);        tree[i].flag^=1;        return;    }    pushdown(i);    int mid=(tree[i].l+tree[i].r)>>1;    if(r<=mid)        negval(l,r,i*2);    else if(l>mid)        negval(l,r,i*2+1);    else    {        negval(l,mid,i*2);        negval(mid+1,r,i*2+1);    }    pushup(i);}void query(int l,int r,int i)//区间查找{    if(tree[i].l==l&&tree[i].r==r)    {        Max=max(Max,tree[i].maxi);        return;    }    pushdown(i);    int mid=(tree[i].l+tree[i].r)>>1;    if(r<=mid)        query(l,r,i*2);    else if(l>mid)        query(l,r,i*2+1);    else    {        query(l,mid,i*2);        query(mid+1,r,i*2+1);    }    pushup(i);}int findmax(int u,int v)//树形图转换为线段树结构,并查找最大值{    int f1=top[u];    int f2=top[v];    int ans=-inf;    while(f1!=f2)    {        if(deep[f1]<deep[f2])        {            swap(f1,f2);            swap(u,v);        }        Max=-inf;        query(p[f1],p[u],1);        ans=max(ans,Max);        u=fa[f1];        f1=top[u];    }    if(v==u)return ans;    if(deep[u]>deep[v])swap(u,v);    Max=-inf;    query(p[son[u]],p[v],1);    ans=max(ans,Max);    return ans;}void neg(int u,int v)//树形图转换为线段树结构,并修改区间值{    int f1=top[u];    int f2=top[v];    while(f1!=f2)    {        if(deep[f1]<deep[f2])        {            swap(f1,f2);            swap(u,v);        }        negval(p[f1],p[u],1);        u=fa[f1];        f1=top[u];    }    if(v==u)return;    if(deep[u]>deep[v])swap(u,v);    negval(p[son[u]],p[v],1);    return;}struct Edge{    int u,v,w;}e[M];int main(){    int T,i,n;    cin>>T;    while(T--)    {        scanf("%d",&n);        init();        for(i=1;i<n;i++)        {            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);            add(e[i].u,e[i].v);            add(e[i].v,e[i].u);        }        dfs(1,1,0);        getpos(1,1);        for(i=1;i<n;i++)        {            if(deep[e[i].u]<deep[e[i].v])                swap(e[i].v,e[i].u);            a[p[e[i].u]]=e[i].w;        }        make(1,pos-1,1);        char ch[22];        int x,y;        while(scanf("%s",ch),strcmp(ch,"DONE")!=0)        {            scanf("%d%d",&x,&y);            if(ch[0]=='Q')            {                printf("%d\n",findmax(x,y));            }            else if(ch[0]=='C')            {                change(p[e[x].u],y,1);            }            else                neg(x,y);        }    }    return 0;}


0 0
原创粉丝点击