[BZOJ1036][JZOJ2256]【ZJOI2008】树的统计(树链剖分模板)

Description

一棵树上有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本身

Solution

链剖裸题。。。。。。

Code

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
struct note
{
    int l,r,sum,mx,ls,rs;   
};
struct nt1
{
    int x,y;    
};
note tree[100001];
int top[30001],deep[30001],size[30001],pt[30001],dfn[30001],ft[30001],son[30001],a[30001],lazy[100001];
nt1 a1[60001];
int a2[30001][2];
int n,m,dfm;
bool cmp(nt1 x,nt1 y)
{
    return x.x<y.x;
}
void give(int f,int k)
{
    tree[k].mx=lazy[f];
    tree[k].sum=(tree[k].r-tree[k].l+1)*lazy[f];
}
void newptl(int f,int l,int r)
{
    if (tree[f].ls==0)
    {
        tree[f].ls=++m;
        tree[m].l=l;
        tree[m].r=r;
    }
}
void newptr(int f,int l,int r)
{
    if (tree[f].rs==0)
    {
        tree[f].rs=++m;
        tree[m].l=l;
        tree[m].r=r;
    }
}
void find(int now,int l,int r,int &sm,int &ma)
{
    if (tree[now].l==l&&tree[now].r==r)
    {
        sm=tree[now].sum;
        ma=tree[now].mx;
        return;
    }
    int ls=tree[now].ls,rs=tree[now].rs;
    if (lazy[now]!=1802201963)
    {
        if (ls!=0) give(now,ls);
        if (rs!=0) give(now,rs);
        lazy[now]=1802201963;
    }
    int mid=(tree[now].l+tree[now].r)/2;
    if (r<=mid) find(ls,l,r,sm,ma);
    else if(l>mid) find(rs,l,r,sm,ma);
    else
    {
        int s1,m1;
        find(ls,l,mid,sm,ma);
        find(rs,mid+1,r,s1,m1);
        sm+=s1;
        ma=max(ma,m1);
    }
    tree[now].sum=tree[tree[now].ls].sum+tree[tree[now].rs].sum;
    tree[now].mx=max(tree[tree[now].ls].mx,tree[tree[now].rs].mx);
}
void ask(int u,int v,int &sm,int &ma,bool uh,bool vh)
{
    int s1=0,m1=-1802201963,s2=0,m2=-1802201963;
    if (u==v) 
    {
        if (uh==0&&vh==0)
        {
            find(1,dfn[u],dfn[v],s1,m1);
            sm=s1;
            ma=m1;
            return;
        }
        sm=0;
        ma=-1802201963;
        return;
    }
    int f1=top[u],f2=top[v];
    if (f1==f2)
    {
        if (deep[u]>deep[v]) swap(u,v);
        find(1,dfn[u],dfn[v],sm,ma);
        return;
    }
    else
    {
        if (deep[f1]<deep[f2]) 
        {
            swap(u,v);
            swap(f1,f2);
            swap(uh,vh);
        }
        find(1,dfn[f1],dfn[u],s1,m1);
        if (ft[f1]==f1) ask(ft[f1],v,s2,m2,1,vh);
        else ask(ft[f1],v,s2,m2,0,vh);
        sm=s1+s2;
        ma=max(m1,m2);
    }
}
void change(int now,int l,int r,int dt)
{
    if (tree[now].l==l&&tree[now].r==r)
    {
        tree[now].mx=dt;
        tree[now].sum=(r-l+1)*dt;
        lazy[now]=dt;
        return;
    }
    int ls=tree[now].ls,rs=tree[now].rs;
    int mid=(tree[now].l+tree[now].r)/2;
    if (lazy[now]!=1802201963)
    {
        if (ls!=0) give(now,ls);
        if (rs!=0) give(now,rs);
        lazy[now]=1802201963;
    }
    if (r<=mid)
    {
        newptl(now,tree[now].l,mid);
        change(tree[now].ls,l,r,dt);
    }
    else if(l>mid)
    {
        newptr(now,mid+1,tree[now].r);
        change(tree[now].rs,l,r,dt);
    }
    else
    {
        newptl(now,tree[now].l,mid);
        newptr(now,mid+1,tree[now].r);
        change(tree[now].ls,l,mid,dt);
        change(tree[now].rs,mid+1,r,dt);
    }
    tree[now].sum=tree[tree[now].ls].sum+tree[tree[now].rs].sum;
    tree[now].mx=max(tree[tree[now].ls].mx,tree[tree[now].rs].mx);
}
void dfs1(int k,int f,int dep)
{
    int i,sz=0,sn=0,wsn=0;
    fo(i,a2[k][0],a2[k][1])
    {
        int p=a1[i].y;
        if (p!=f)
        {
            ft[p]=k;
            dfs1(p,k,dep+1);
            sz+=size[p];
            if (size[p]>sn) 
            {
                sn=size[p];
                wsn=p;
            } 
        }
    }
    size[k]=sz+1;
    son[k]=wsn;
    deep[k]=dep;
}
void dfs2(int k,int f)
{
    dfn[k]=++dfm;
    change(1,dfn[k],dfn[k],a[k]);
    int i;
    if (son[k]!=0)
    {
        top[son[k]]=top[k];
        dfs2(son[k],k);
    }
    fo(i,a2[k][0],a2[k][1])
    {
        int p=a1[i].y;
        if (p!=f&&p!=son[k])
        {
            top[p]=p;
            dfs2(p,k);
        }
    }
}
int main()
{
    cin>>n;
    int i,j,s1,m1;
    fo(i,1,n-1) 
    {
        scanf("%d%d",&a1[2*i-1].x,&a1[2*i-1].y);
        a1[2*i].x=a1[2*i-1].y;
        a1[2*i].y=a1[2*i-1].x;
    }
    sort(a1+1,a1+2*n-1,cmp);
    fo(i,1,2*n-2)
    {
        if (a1[i].x!=a1[i-1].x)
        {
            a2[a1[i].x][0]=i;
            a2[a1[i-1].x][1]=i-1;
        }
    }
    a2[a1[2*n-2].x][1]=2*n-2;
    fo(i,1,n) scanf("%d",&a[i]);
    memset(lazy,107,sizeof(lazy));
    dfs1(1,0,1);
    dfm=0;
    top[1]=1;
    m=1;
    tree[1].l=1;
    tree[1].r=n;
    dfs2(1,0);
    ft[1]=1;
    scanf("\n");
    int cz;
    scanf("%d",&cz);
    scanf("\n");
    int ct=0;
    fo(i,1,cz)
    {
        char c,c1;
        scanf("%c%c",&c,&c1);
        if (c=='C')
        {
            int x,t;
            scanf("ANGE %d%d\n",&x,&t);
            change(1,dfn[x],dfn[x],t);
        }
        else
        {
            int su,ma,u,v;
            if (c1=='M') scanf("AX %d%d\n",&u,&v);
            else scanf("UM %d%d\n",&u,&v);
            if (u==v) find(1,dfn[u],dfn[v],su,ma);              
            else ask(u,v,su,ma,0,0);

            if (c1=='M') printf("%d\n",ma);
            else printf("%d\n",su);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值