[bzoj] 1036 Count

Posted Mrha

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj] 1036 Count相关的知识,希望对你有一定的参考价值。

原题

树链剖分板子题

树剖详解:

#include<cstdio>
#include<algorithm>
typedef long long ll;
#define N 30010
using namespace std;
int n,x,y,m,a[N],f[N],dfn[N],deep[N],head[N],cnt=1,tp[N],ref[N],t,son[N],size[N];
char s[10];
struct hhh
{
    int to,next;
}edge[2*N];
struct node
{
    int l,r,data,mx;
}tre[4*N];

int read()
{
    int ans=0,fu=1;
    char j=getchar();
    for (;(j<‘0‘ || j>‘9‘) && j!=‘-‘;j=getchar()) ;
    if (j==‘-‘) fu=-1,j=getchar();
    for (;j>=‘0‘ && j<=‘9‘;j=getchar()) ans*=10,ans+=j-‘0‘;
    return ans*fu;
}

void add(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}

void dfs1(int x,int fa,int dep)
{
    f[x]=fa;
    deep[x]=dep+1;
    int mx=0;
    for (int i=head[x],v;i;i=edge[i].next)
    {
    v=edge[i].to;
    if (v!=fa)
    {
        dfs1(v,x,dep+1);
        size[x]+=size[v];
        if (size[v]>mx) son[x]=v,mx=size[v];
    }
    }
    size[x]++;
}

void dfs2(int x,int top)
{
    dfn[x]=++t;
    ref[t]=x;
    tp[x]=top;
    if (son[x]) dfs2(son[x],top);
    for (int i=head[x],v;i;i=edge[i].next)
    {
    v=edge[i].to;
    if (v!=son[x] && v!=f[x])
        dfs2(v,v);
    }
}

void build(int i,int l,int r)
{
    tre[i].l=l;
    tre[i].r=r;
    if (l==r)
    {
    tre[i].data=a[ref[l]];
    tre[i].mx=a[ref[l]];
    return ;
    }
    int mid=(l+r)>>1;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
    tre[i].data=tre[i*2].data+tre[i*2+1].data;
    tre[i].mx=max(tre[i*2].mx,tre[i*2+1].mx);
}

void modify(int i,int x,int y)
{
    if (tre[i].l==x && tre[i].l==tre[i].r)
    {
    tre[i].data=y;
    tre[i].mx=y;
    return ;
    }
    int mid=(tre[i].l+tre[i].r)>>1;
    if (x>mid) modify(i*2+1,x,y);
    else modify(i*2,x,y);
    tre[i].data=tre[i*2].data+tre[i*2+1].data;
    tre[i].mx=max(tre[i*2].mx,tre[i*2+1].mx);
}

ll query(int i,int l,int r,int p)
{
    if (tre[i].l==l && tre[i].r==r)
    if (p) return tre[i].data;
    else return tre[i].mx;
    int mid=(tre[i].l+tre[i].r)>>1;
    if (l>mid) return query(i*2+1,l,r,p);
    else if (r<=mid) return query(i*2,l,r,p);
    else if (p) return query(i*2,l,mid,p)+query(i*2+1,mid+1,r,p);
    else return max(query(i*2,l,mid,p),query(i*2+1,mid+1,r,p));
}

ll pathquery(int u,int v,int p)
{
    ll ans=0,tmp=-1000000000;
    while (tp[u]!=tp[v])
    {
    if (deep[tp[u]]<deep[tp[v]]) swap(u,v);
    if (p) ans+=query(1,dfn[tp[u]],dfn[u],p);
    else tmp=max(tmp,query(1,dfn[tp[u]],dfn[u],p));
    u=f[tp[u]];
    }
    if (deep[u]>deep[v]) swap(u,v);
    if (p) return ans+query(1,dfn[u],dfn[v],p);
    else return max(tmp,query(1,dfn[u],dfn[v],p));
}

int main()
{
    n=read();
    for (int i=1;i<n;i++)
    {
    x=read();
    y=read();
    add(x,y);
    add(y,x);
    }
    for (int i=1;i<=n;i++) a[i]=read();
    dfs1(1,0,0);
    dfs2(1,1);
    build(1,1,n);
    m=read();
    while (m--)
    {
    scanf("%s",s);
    x=read();
    y=read();
    if (s[1]==‘M‘)
        printf("%lld\n",pathquery(x,y,0));
    else if (s[1]==‘S‘)
        printf("%lld\n",pathquery(x,y,1));
    else modify(1,dfn[x],y);
    }
    return 0;
}

以上是关于[bzoj] 1036 Count的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1036: [ZJOI2008]树的统计Count (树链剖分)

BZOJ 1036 树的统计count

BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

bzoj 1036: [ZJOI2008]树的统计Count

bzoj 1036: [ZJOI2008]树的统计Count

[bzoj] 1036 Count