bzoj 1036

来源:互联网 发布:sqlserver基础知识 编辑:程序博客网 时间:2024/05/22 12:55
题意:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I

II. QSUM u v: 询问从点u到点v的路径上的节点的权值和


分析:树链剖分


技能:

    for (;belong[x]^belong[y];)
    {
        if (deep[belong[x]]<deep[belong[y]]) swap(x,y);
        ans+=query(1,1,n,pos[belong[x]],pos[x]);
        x=fa[belong[x]];
    }


    deep[belong[x]]<deep[belong[y]比较的是链顶的深度大小


代码:

#include<bits/stdc++.h>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;++i)
#define dep(i,j,k) for (int i=j;i>=k;--i)
#define to e[i].v
#define Cl(a) memset(a,0,sizeof(a))
#define N 30010
#define inf 1235467890

struct node{
    int v,next;
}e[N<<2];

int Max[N<<2],sum[N<<2],fa[N<<2],pos[N<<2],size[N<<2],head[N<<2],deep[N<<2],belong[N<<2];
int id,n,m,sz;

int read()
{
    int f=1,x=0;char ch=getchar();
    for (;ch>'9'||ch<'0';ch=getchar()) if (ch=='-') f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    return x*f;
}

void add(int u,int v)
{
    e[id].v=v;
    e[id].next=head[u];
    head[u]=id++;
}

void dfs1(int u)
{
    size[u]=1;
    for (int i=head[u];i;i=e[i].next)
    if (to^fa[u])
    {
        deep[to]=deep[u]+1;
        fa[to]=u;
        dfs1(to);
        size[u]+=size[to];
    }
}

void dfs2(int u,int chain)
{
    pos[u]=++sz; belong[u]=chain; int k=0;
    for (int i=head[u];i;i=e[i].next)
        if (deep[to]>deep[u] && size[to]>size[k]) k=to;
    if (k==0) return; dfs2(k,chain);
    for (int i=head[u];i;i=e[i].next)
        if (deep[to]>deep[u] && k^to) dfs2(to,to);
}

void pushup(int root)
{
    Max[root]=max(Max[root<<1],Max[root<<1|1]);
    sum[root]=sum[root<<1]+sum[root<<1|1];
}

int query_Max(int root,int l,int r,int L,int R)
{
    if (L<=l && r<=R) return Max[root];
    int mid=l+r>>1,Mx=-inf;
    if (L<=mid) Mx=max(query_Max(root<<1,l,mid,L,R),Mx);
    if (mid<R) Mx=max(query_Max(root<<1|1,mid+1,r,L,R),Mx);
    return Mx;
}

int query(int root,int l,int r,int L,int R)
{
    if (L<=l && r<=R) return sum[root];
    int mid=l+r>>1,ans=0;
    if (L<=mid) ans+=query(root<<1,l,mid,L,R);
    if (mid<R) ans+=query(root<<1|1,mid+1,r,L,R);
    return ans;
}

void insert(int root,int l,int r,int x,int y)
{
    if (l==r)
    {
        sum[root]=Max[root]=y;
        return;
    }
    int mid=l+r>>1;
    if (x<=mid) insert(root<<1,l,mid,x,y);
    if (mid<x) insert(root<<1|1,mid+1,r,x,y);
    pushup(root);
}

void swap(int &a,int &b) {int t=a;a=b;b=t;}

int Query(int x,int y)
{
    int ans=0;
    for (;belong[x]^belong[y];)
    {
        if (deep[belong[x]]<deep[belong[y]]) swap(x,y);
        ans+=query(1,1,n,pos[belong[x]],pos[x]);
        x=fa[belong[x]];
    }
    if (pos[x]>pos[y]) swap(x,y);
    ans+=query(1,1,n,pos[x],pos[y]);
    return ans;
}

int Query_Max(int x,int y)
{
    int Mx=-inf;
    for (;belong[x]^belong[y];)
    {
        if (deep[belong[x]]<deep[belong[y]]) swap(x,y);
        Mx=max(query_Max(1,1,n,pos[belong[x]],pos[x]),Mx);
        x=fa[belong[x]];
    }
    if (pos[x]>pos[y]) swap(x,y);
    Mx=max(query_Max(1,1,n,pos[x],pos[y]),Mx);
    return Mx;
}

int main()
{
    n=read(); id=1;
    rep(i,1,n-1)
    {
        int u=read(),v=read();
        add(u,v); add(v,u);
    }
    dfs1(1);
    dfs2(1,1);
    rep(i,1,n)
    {
        int x=read();
        insert(1,1,n,pos[i],x);
    }
    m=read(); char ch[10];
    rep(i,1,m)
    {
        scanf("%s",ch+1);
        if (ch[1]=='C')
        {
            int x=read(),y=read();
            insert(1,1,n,pos[x],y);
        }
        else if (ch[1]=='Q' && ch[2]=='S')
        {
            int x=read(),y=read();
            printf("%d\n",Query(x,y));
        }
        else
        {
            int x=read(),y=read();
            printf("%d\n",Query_Max(x,y));
        }
    }
    return 0;
}

原创粉丝点击