bzoj 1036 樹鏈剖分

1036: [ZJOI2008]樹的統計Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 18993  Solved: 7748
[Submit][Status][Discuss]

Description

  一棵樹上有n個節點,編號分別爲1到n,每一個節點都有一個權值w。咱們將如下面的形式來要求你對這棵樹完成
一些操做: I. CHANGE u t : 把結點u的權值改成t II. QMAX u v: 詢問從點u到點v的路徑上的節點的最大權值 I
II. QSUM u v: 詢問從點u到點v的路徑上的節點的權值和 注意:從點u到點v的路徑上的節點包括u和v自己php

Input

  輸入的第一行爲一個整數n,表示節點的個數。接下來n – 1行,每行2個整數a和b,表示節點a和節點b之間有
一條邊相連。接下來n行,每行一個整數,第i行的整數wi表示節點i的權值。接下來1行,爲一個整數q,表示操做
的總數。接下來q行,每行一個操做,以「CHANGE u t」或者「QMAX u v」或者「QSUM u v」的形式給出。 
對於100%的數據,保證1<=n<=30000,0<=q<=200000;中途操做中保證每一個節點的權值w在-30000到30000之間。ios

Output

  對於每一個「QMAX」或者「QSUM」的操做,每行輸出一個整數表示要求輸出的結果。ui

Sample Input

4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4

Sample Output

4
1
2
2
10
6
5
6
5
16

HINT

 

Source

 代碼:
//和上一題稍微不一樣,這題權值在點上。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=30000;
int fa[MAXN+9],son[MAXN+9],lev[MAXN+9],top[MAXN+9],id[MAXN+9],head[MAXN+9],size[MAXN+9],val[MAXN+9];
int max_[MAXN*4+9],sum_[MAXN*4+9],tot,cnt;
struct Edge
{
    int u,v,next;
}edge[MAXN*2+9];
void init()
{
    tot=cnt=0;
    for(int i=0;i<=MAXN;i++) fa[i]=top[i]=i;
    memset(sum_,0,sizeof(sum_));
    memset(head,-1,sizeof(head));
}
void add(int x,int y)
{
    edge[tot].u=x;edge[tot].v=y;
    edge[tot].next=head[x];
    head[x]=tot++;
    edge[tot].u=y;edge[tot].v=x;
    edge[tot].next=head[y];
    head[y]=tot++;
}
void dfs1(int x,int d)
{
    lev[x]=d;
    son[x]=0;
    size[x]=1;
    for(int i=head[x];i!=-1;i=edge[i].next){
        int y=edge[i].v;
        if(y==fa[x]) continue;
        fa[y]=x;
        dfs1(y,d+1);
        size[x]+=size[y];
        if(size[son[x]]<size[y]) son[x]=y;
    }
}
void dfs2(int x,int tp)
{
    top[x]=tp;
    id[x]=++cnt;
    if(son[x]) dfs2(son[x],tp);
    for(int i=head[x];i!=-1;i=edge[i].next){
        int y=edge[i].v;
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}
void pushup(int rt)
{
    max_[rt]=max(max_[rt<<1],max_[rt<<1|1]);
    sum_[rt]=sum_[rt<<1]+sum_[rt<<1|1];
}
void build(int l,int r,int rt)
{
    if(l==r){
        max_[rt]=sum_[rt]=val[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);
}
void update(int id,int c,int l,int r,int rt)
{
    if(l==r){
        max_[rt]=sum_[rt]=c;
        return;
    }
    int mid=(l+r)>>1;
    if(id<=mid) update(id,c,l,mid,rt<<1);
    else update(id,c,mid+1,r,rt<<1|1);
    pushup(rt);
}
int query1(int ql,int qr,int l,int r,int rt)
{
    if(ql<=l&&qr>=r) return max_[rt];
    int mid=(l+r)>>1,ans=-MAXN-9;
    if(ql<=mid) ans=max(ans,query1(ql,qr,l,mid,rt<<1));
    if(qr>mid) ans=max(ans,query1(ql,qr,mid+1,r,rt<<1|1));
    return ans;
}
int query2(int ql,int qr,int l,int r,int rt)
{
    if(ql<=l&&qr>=r) return sum_[rt];
    int mid=(l+r)>>1,ans=0;
    if(ql<=mid) ans+=query2(ql,qr,l,mid,rt<<1);
    if(qr>mid) ans+=query2(ql,qr,mid+1,r,rt<<1|1);
    return ans;
}
int solve(int l,int r,bool f)
{
    int ltp=top[l],rtp=top[r],ans=(f?0:-MAXN-9);
    while(ltp!=rtp){
        if(lev[rtp]<lev[ltp]){
            swap(ltp,rtp);
            swap(l,r);
        }
        if(!f) ans=max(ans,query1(id[rtp],id[r],1,cnt,1));
        else ans+=query2(id[rtp],id[r],1,cnt,1);
        r=fa[rtp];
        rtp=top[r];
    }
    if(lev[r]>lev[l]) swap(l,r);
    if(!f) ans=max(ans,query1(id[r],id[l],1,cnt,1));
    else ans+=query2(id[r],id[l],1,cnt,1);
    return ans;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int n,q;
    scanf("%d",&n);
    init();
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
    }
    dfs1(1,1);
    dfs2(1,1);
    for(int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        val[id[i]]=x;
    }
    build(1,cnt,1);
    scanf("%d",&q);
    char ch[10];
    while(q--){
        int x,y;
        scanf("%s%d%d",ch,&x,&y);
        if(ch[0]=='C') update(id[x],y,1,cnt,1);
        else if(ch[1]=='M') printf("%d\n",solve(x,y,0));
        else printf("%d\n",solve(x,y,1));
    }
    return 0;
}
相關文章
相關標籤/搜索