[luogu2590] [ZJOI2008]树的统计

传送门

emmm树剖裸题,就线段树维护一下最大值和权值和就行了。

这里有一个点就是:因为会出现负数,所以查最大值的时候不能初始化为0,这样就没法维护负值

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 30005

struct Node {
    long long sum,maxx;
}seg[MAXN<<2];

struct edge {
    int v,next;
}G[MAXN<<1];
int head[MAXN];

long long val[MAXN],a[MAXN];
int dfn[MAXN],top[MAXN];
int size[MAXN],son[MAXN],fa[MAXN],d[MAXN];

int N,M,tot = 0,num = 0;

#define lson (rt<<1)
#define rson (rt<<1|1)
#define mid ((l+r)>>1)

inline void add(int u,int v) {
    G[++tot].v = v;G[tot].next = head[u];head[u] = tot;
}

inline void pushup(int rt) {
    seg[rt].sum = seg[lson].sum + seg[rson].sum;
    seg[rt].maxx = std::max(seg[lson].maxx,seg[rson].maxx);
}

void Build(int rt,int l,int r) {
    if(l==r) {
        seg[rt].sum = val[l];
        seg[rt].maxx = val[l];
        return;
    }
    Build(lson,l,mid);
    Build(rson,mid+1,r);
    pushup(rt);
}

void update(int L,long long C,int rt,int l,int r) {
    if(l==r&&l==L) {
        seg[rt].maxx = C;
        seg[rt].sum = C;
        return;
    }
    if(L<=mid) update(L,C,lson,l,mid);
    else update(L,C,rson,mid+1,r);
    pushup(rt);
}

long long max_query(int L,int R,int rt,int l,int r) {
    if(L<=l&&R>=r) return seg[rt].maxx;
    if(L>r||R<l) return -30000;
    long long maxx = -30000;
    if(L<=mid) maxx = std::max(maxx,max_query(L,R,lson,l,mid));
    if(R>mid) maxx = std::max(maxx,max_query(L,R,rson,mid+1,r));
    return maxx;
}

long long sum_query(int L,int R,int rt,int l,int r) {
    if(L<=l&&R>=r) return seg[rt].sum;
    if(L>r||R<l) return 0;
    long long ans = 0;
    if(L<=mid) ans += sum_query(L,R,lson,l,mid);
    if(R>mid) ans += sum_query(L,R,rson,mid+1,r);
    return ans;
}

void dfs1(int u,int father) {
    d[u] = d[father] + 1; fa[u] = father;
    son[u] = 0; size[u] = 1;
    for(int i=head[u];i;i=G[i].next) {
        int v = G[i].v;
        if(v==father) continue;
        dfs1(v,u);
        size[u] += size[v];
        if(size[son[u]] < size[v]) son[u] = v;
    }
}

void dfs2(int u,int tp) {
    dfn[u] = ++num;
    top[u] = tp;
    val[num] = a[u];
    if(son[u]) dfs2(son[u],tp);
    for(int i=head[u];i;i=G[i].next) {
        int v = G[i].v;
        if(v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}

inline int get_opt() {
    int opt;
    char ch = getchar();
    while(ch!='C'&&ch!='Q') ch = getchar();
    if(ch=='C') opt = 1;
    else {
        ch = getchar();
        opt = ch=='M' ? 2 : 3;
    }    
    while((ch=getchar())!=' ');
    return opt;
}

long long max_query_cut(int u,int v) {
    long long maxx = -30000;
    while(top[u]!=top[v]) {
        if(d[top[u]]<d[top[v]]) std::swap(u,v);
        maxx = std::max(maxx,max_query(dfn[top[u]],dfn[u],1,1,N));
        u = fa[top[u]];
    }
    if(d[u]>d[v]) std::swap(u,v);
    maxx = std::max(maxx,max_query(dfn[u],dfn[v],1,1,N));
    return maxx;
}

long long sum_query_cut(int u,int v) {
    long long ans = 0;
    while(top[u]!=top[v]) {
        if(d[top[u]]<d[top[v]]) std::swap(u,v);
        ans += sum_query(dfn[top[u]],dfn[u],1,1,N);
        u = fa[top[u]];
    }
    if(d[u]>d[v]) std::swap(u,v);
    ans += sum_query(dfn[u],dfn[v],1,1,N);
    return ans;
}

int main() {

    int u,v;
    scanf("%d",&N);
    for(int i=1;i<N;++i) {
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    for(int i=1;i<=N;++i) scanf("%lld",&a[i]);
    
    d[1] = 0;size[0] = 0;
    dfs1(1,1);
    dfs2(1,1);
    Build(1,1,N);

    scanf("%d",&M);
    for(int i=1;i<=M;++i) {
        int opt = get_opt();
        scanf("%d%d",&u,&v);
        if(opt==1) update(dfn[u],v,1,1,N);
        else if(opt==2) printf("%lld\n",max_query_cut(u,v));
        else printf("%lld\n",sum_query_cut(u,v));
    }

    return 0;
}
posted @ 2018-11-21 20:02  Neworld1111  阅读(224)  评论(0编辑  收藏  举报