SPOJ QTREEQuery on a tree(树链剖分-点更新-区间最值查询-入边)

来源:互联网 发布:dotnet可以用java吗 编辑:程序博客网 时间:2024/06/12 03:46

题意:

操作1.更改第i条边权值

操作2.查询i->j的路径最大值

操作3 跳出

#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;const int maxn = 100005;int dep[maxn],siz[maxn],fa[maxn],id[maxn],son[maxn],val[maxn],top[maxn];int topw,head[maxn],cnt;///dep 深度 siz个数 fa父 top祖 son重儿子 val值/// e数组 初始入边  edge数组存边struct Edge{    int to,next;} edge[maxn*2];struct treex{    int x,y,val;} e[maxn];void add(int u,int v ){    edge[cnt].to=v;    edge[cnt].next=head[u];    head[u]=cnt++;}void dfs1(int u,int f,int d){    dep[u]=d;    siz[u]=1;    son[u]=0;    fa[u]=f;    for(int i =head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].to;        if(v==fa[u])            continue;        dfs1(v,u,d+1);        siz[u]+=siz[v];        if(siz[son[u]]<siz[v])            son[u]=v;    }}void dfs2(int u,int tp){    top[u]=tp;    id[u]=++topw;    if(son[u])        dfs2(son[u],tp);    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].to;        if(v==fa[u]||v==son[u])            continue;        dfs2(v,v);    }}struct node{    int left,right,maxx;}tree[maxn*4];void push_up(int i){    tree[i].maxx=max(tree[i<<1].maxx,tree[i<<1|1].maxx);}void build(int i,int left,int right){    tree[i].left=left;    tree[i].right=right;    if(left==right)    {        tree[i].maxx=val[left];        return ;    }    int mid=(tree[i].left+tree[i].right)>>1;    build(i<<1,left,mid);    build(i<<1|1,mid+1,right);    push_up(i);}void update(int i,int aim,int w){    if(tree[i].left==tree[i].right&&tree[i].left==aim)    {        tree[i].maxx=w;        return ;    }    int mid=(tree[i].left+tree[i].right)>>1;    if(aim<=mid)        update(i<<1,aim,w);    else        update(i<<1|1,aim,w);    push_up(i);}int  query(int i,int left,int right){    if(tree[i].left>=left&&tree[i].right<=right)        return tree[i].maxx;    int mid=(tree[i].left+tree[i].right)>>1;    if(right<=mid)        return query(i<<1,left,right);    else if(left>mid)        return query(i<<1|1,left,right);    else        return max(query(i<<1,left,mid),query(i<<1|1,mid+1,right));}int  change(int u,int v){    int tpu=top[u],tpv=top[v];    int ans=0;    while(tpu!=tpv)    {        if(dep[tpu]<dep[tpv])            swap(u,v),swap(tpu,tpv);        ans=max(ans,query(1,id[tpu],id[u]));        u=fa[tpu];        tpu=top[u];    }    if(u!=v)    {        if(dep[u]>dep[v])            swap(u,v);        ans=max(ans,query(1,id[son[u]],id[v]));    }    return ans;}int main(){    int n,m,s;    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        memset(head,-1,sizeof(head));        for(int i=1;i<n;i++)        {            scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].val);            add(e[i].x,e[i].y);            add(e[i].y,e[i].x);        }        topw=0;        dfs1(1,0,1);        dfs2(1,1);        //将之前给出的边的权值,赋给点。        for(int i=1;i<n;i++)        {            if(dep[e[i].x] < dep[e[i].y])                swap(e[i].x,e[i].y);            val[id[e[i].x]] = e[i].val;        }        char op[10];        build(1,1,topw);        while(1)        {            scanf("%s",op);            if(op[0]=='Q')            {                int l,r;                scanf("%d%d",&l,&r);                printf("%d\n",change(l,r));            }            else if(op[0]=='C')            {                int x,y;                scanf("%d%d",&x,&y);                update(1,id[e[x].x],y);            }            else                break;        }    }    return 0;}


原创粉丝点击