【ZJOI2008】树的统计

题目

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身

分析

只用单点修改的树链剖分模板题。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
using namespace std;
struct trees
{
    int v,mx,l,r;
}tree[90000];
int d[90000],dson[90000],deep[90000],size[90000],fa[90000],top[90000],n,m,v[90000],bef[90000],tot,mi2[30];
int next[90000],last[90000],to[90000],po;
int ans;
int bj(int x,int y)
{
    next[++tot]=last[x];
    last[x]=tot;
    to[tot]=y;
}
int dg(int x)
{
    size[x]=1;
    int mx=0;
    for(int i=last[x];i;i=next[i])
    {
        if(to[i]!=fa[x])
        {
            fa[to[i]]=x;
            deep[to[i]]=deep[x]+1;
            dg(to[i]);
            size[x]+=size[to[i]];
            if(size[to[i]]>mx)
            {
                mx=size[to[i]];
                dson[x]=to[i];
            }
        }
    }
}
int dg1(int x)
{
    bef[x]=++tot;
    d[tot]=x;
    if(top[x]==0)
    {
        top[x]=x;
    }
    if(dson[x])
    {
        top[dson[x]]=top[x];
        dg1(dson[x]);
    }
    for(int i=last[x];i;i=next[i])
    {
        if(to[i]!=fa[x] && to[i]!=dson[x])
        {
            dg1(to[i]);
        }
    }
}
int treechange(int l,int r,int pos,int aim,int value)
{
    int mid=(l+r)/2;
    tree[pos].l=l;
    tree[pos].r=r;
    if(l==r)
    {
        tree[pos].v=value;
        tree[pos].mx=value;
        return 0;
    }
    if(aim<=mid)
    {
        treechange(l,mid,pos*2,aim,value);
    }
    else
    {
        treechange(mid+1,r,pos*2+1,aim,value);
    }
    tree[pos].v=tree[pos*2].v+tree[pos*2+1].v;
    tree[pos].mx=max(tree[pos*2].mx,tree[pos*2+1].mx);
}
int findmx(int l,int r,int pos,int aiml,int aimr)
{
    int mid=(l+r)/2;
    if(l==aiml && r==aimr)
    {
        ans=max(ans,tree[pos].mx);
        return 0;
    }
    if(aimr<=mid)
    {
        findmx(l,mid,pos*2,aiml,aimr);
    }
    else
    if(aiml>mid)
    {
        findmx(mid+1,r,pos*2+1,aiml,aimr);
    }
    else
    {
        findmx(l,mid,pos*2,aiml,mid);
        findmx(mid+1,r,pos*2+1,mid+1,aimr);
    }
}
int findmax(int x,int y)
{
    ans=-maxlongint;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]>=deep[top[y]])
        {
            findmx(1,n,1,bef[top[x]],bef[x]);
            x=fa[top[x]];
        }
        else
        {
            findmx(1,n,1,bef[top[y]],bef[y]);
            y=fa[top[y]];
        }
    }
    if(deep[x]>=deep[y])
    {
        findmx(1,n,1,bef[y],bef[x]);
    }
    else
    {
        findmx(1,n,1,bef[x],bef[y]);
    }
    printf("%d\n",ans);
}
int findsm(int l,int r,int pos,int aiml,int aimr)
{
    int mid=(l+r)/2;
    if(l==aiml && r==aimr)
    {
        ans+=tree[pos].v;
        return 0;
    }
    if(aimr<=mid)
    {
        findsm(l,mid,pos*2,aiml,aimr);
    }
    else
    if(aiml>mid)
    {
        findsm(mid+1,r,pos*2+1,aiml,aimr);
    }
    else
    {
        findsm(l,mid,pos*2,aiml,mid);
        findsm(mid+1,r,pos*2+1,mid+1,aimr);
    }
}
int findsum(int x,int y)
{
    ans=0;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]>=deep[top[y]])
        {
            findsm(1,n,1,bef[top[x]],bef[x]);
            x=fa[top[x]];
        }
        else
        {
            findsm(1,n,1,bef[top[y]],bef[y]);
            y=fa[top[y]];
        }
    }
    if(deep[x]>=deep[y])
    {
        findsm(1,n,1,bef[y],bef[x]);
    }
    else
    {
        findsm(1,n,1,bef[x],bef[y]);
    }
    printf("%d\n",ans);
}
int main()
{
    mi2[1]=1;
    for(int i=2;i<=25;i++)
        mi2[i]=mi2[i-1]*2;
    scanf("%d",&n);
    for(int i=1;i<=n-1;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        bj(x,y);
        bj(y,x);
    }
    deep[1]=1;
    dg(1);
    tot=0;
    dg1(1);
    for(int i=1;i<=90000-1;i++)
        tree[i].mx=-maxlongint;
    for(int i=1;i<=25;i++)
    {
        if(mi2[i]*2>=tot)
        {
            po=mi2[i]*2-1;
            break;
        }
    }
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        treechange(1,n,1,bef[i],x);
    }
    scanf("%d\n",&m);
    char c;
    for(int i=1;i<=m;i++)
    {
        c=getchar();
        if(c=='C')
        {
            int x,y;
            scanf("HANGE %d %d\n",&x,&y);
            treechange(1,n,1,bef[x],y);
        }
        else
        {
            c=getchar();
            if(c=='M')
            {
                int x,y;
                scanf("AX %d %d\n",&x,&y);
                findmax(x,y);
            }
            else
            {
                int x,y;
                scanf("UM %d %d\n",&x,&y);
                findsum(x,y);
            }
        }
        
    }
}

猜你喜欢

转载自www.cnblogs.com/chen1352/p/9026690.html
今日推荐