bzoj 1036 树链剖分+线段树 裸题

Posted %%%%%

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1036 树链剖分+线段树 裸题相关的知识,希望对你有一定的参考价值。

HYSBZ - 1036

题意:中文题

思路:树链剖分裸题,线段树写得比较搓,(在线段树上修改节点u的时候应该修改u映射到线段树后的节点序号,这里wa了半年,真的是半年)

AC代码:

#include "iostream"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#define ll long long
#define bug cout<<"UUUUUUUU"<<endl;
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int MAX=1e5+100;
int son[MAX],siz[MAX],fa[MAX],de[MAX],top[MAX],tip[MAX];
struct Edge{
    int to;
    int next;
};
Edge e[MAX<<1];
int tot=1,cnt=1,head[MAX];
void add(int u, int v){
    e[tot].to=v;
    e[tot].next=head[u];
    head[u]=tot++;
}
void Dfs1(int u, int f){
    siz[u]=1;
    fa[u]=f;
    de[u]=de[f]+1;
    for(int i=head[u]; i!=-1; i=e[i].next){
        int v=e[i].to;
        if(v==fa[u]) continue;
        Dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]]) son[u]=v;
    }
}
void Dfs2(int u, int tp){
    tip[u]=cnt++;
    top[u]=tp;
    if(son[u]) Dfs2(son[u],tp);
    for(int i=head[u]; i!=-1; i=e[i].next){
        int v=e[i].to;
        if(v!=fa[u]&&son[u]!=v) Dfs2(v,v);
    }
}
int w[MAX<<2],sum[MAX<<2],m[MAX];
void push_up(int rt){
    m[rt]=max(m[rt<<1],m[rt<<1|1]);
    sum[rt]=(sum[rt<<1]+sum[rt<<1|1]);
}
void Build(int rt, int l, int r){
    if(l==r){
        sum[rt]=m[rt]=w[l];
        return;
    }
    int mid=l+r>>1;
    Build(rt<<1,l,mid);
    Build(rt<<1|1,mid+1,r);
    push_up(rt);
}
void update(int rt, int L, int R, int p,int w){
    if(L==R){
        sum[rt]=m[rt]=w;
        return;
    }
    int mid=L+R>>1;
    if(p<=mid) update(rt<<1,L,mid,p,w);
    else update(rt<<1|1,mid+1,R,p,w);
    push_up(rt);
}
int query_max(int rt,int l, int r, int L, int R){
    if(l==L&&r==R) return m[rt];
    int mid=L+R>>1;
    if(r<=mid) return query_max(rt<<1,l,r,L,mid);
    else if(l>mid) return query_max(rt<<1|1,l,r,mid+1,R);
    else return max(query_max(rt<<1,l,mid,L,mid),query_max(rt<<1|1,mid+1,r,mid+1,R));
}
int query_sum(int rt, int l, int r,int L, int R){
    if(l==L&&r==R) return sum[rt];
    int mid=L+R>>1;
    if(r<=mid) return query_sum(rt<<1,l,r,L,mid);
    else if(l>mid) return query_sum(rt<<1|1,l,r,mid+1,R);
    else return query_sum(rt<<1,l,mid,L,mid)+query_sum(rt<<1|1,mid+1,r,mid+1,R);
}
void get_sum(int u,int v,int n){
    int ans=0;
    while(top[u]!=top[v]){
        if(de[top[v]]<de[top[u]]) swap(u,v);
        ans+=query_sum(1,tip[top[v]],tip[v],1,n);
        v=fa[top[v]];
    }
    if(de[u]<de[v]) swap(u,v);
    ans+=query_sum(1,tip[v],tip[u],1,n);
    printf("%d\n",ans);
}
void get_max(int u, int v,int n){
    int ans=-1<<30;
    while(top[u]!=top[v]){
        if(de[top[v]]<de[top[u]]) swap(u,v);
        ans=max(ans,query_max(1,tip[top[v]],tip[v],1,n));
        v=fa[top[v]];
    }
    if(de[u]<de[v]) swap(u,v);
    ans=max(ans,query_max(1,tip[v],tip[u],1,n));
    printf("%d\n",ans);
}
int main(){
    int n,q,a,b;
    char s[15];
    scanf("%d",&n);
    memset(head,-1,sizeof(head));
    for(int i=1; i<n; ++i){
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    Dfs1(1,1);
    Dfs2(1,1);
    for(int i=1; i<=n; ++i) scanf("%d",&w[tip[i]]);
    Build(1,1,n);
    scanf("%d",&q);
    while(q--){
        getchar();
        scanf("%s%d%d",s,&a,&b);
        if(s[1]==M) get_max(a,b,n);
        else if(s[1]==S) get_sum(a,b,n);
        else update(1,1,n,tip[a],b);
    }
   return 0;
}

 

以上是关于bzoj 1036 树链剖分+线段树 裸题的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

bzoj1036 树的统计(树链剖分+线段树)

bzoj1036[ZJOI2008]树的统计Count 树链剖分+线段树

bzoj1036: [ZJOI2008]树的统计Count(树链剖分+线段树维护)

树链剖分/线段树BZOJ1036-[ZJOI2008]树的统计Count

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