bzoj 1036: [ZJOI2008]树的统计Count (树链剖分+线段树 点权)

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 21194  Solved: 8589
[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本身

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之间。

Output

  对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

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
 
ps:
这道题用cin输入会超时。用了提速的也没用。。
 
实现代码;
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int M = 1e5+10;
vector<int>g[M];
int sum[M<<2],maxx[M<<2];
int cnt,n,q;
int siz[M],son[M],fa[M],top[M],rk[M],tid[M],dep[M],a[M],cnt1,head[M];
struct node{int to,next;}e[M];
void add(int u,int v){
    e[++cnt1].to = v;e[cnt1].next = head[u];head[u] = cnt1;
    e[++cnt1].to = u;e[cnt1].next = head[v];head[v] = cnt1;
}
void dfs1(int u,int faz,int deep){
     dep[u] = deep;
     fa[u] = faz;
     siz[u] = 1;
     for(int i = head[u];i;i=e[i].next){
        int v = e[i].to;
        if(v != fa[u]){
            dfs1(v,u,deep+1);
            siz[u] += siz[v];
            if(son[u] == -1||siz[v] > siz[son[u]])
                son[u] = v;
        }
     }
}

void dfs2(int u,int t){
    top[u] = t;
    tid[u] = cnt;
    rk[cnt] = u;
    cnt++;
    if(son[u] == -1) return;
    dfs2(son[u],t);
    for(int i = head[u];i;i = e[i].next){
        int v = e[i].to;
        if(v != son[u]&&v != fa[u])
            dfs2(v,v);
    }
}

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

void update(int p,int c,int l,int r,int rt){
     if(l == r){
        sum[rt] = maxx[rt] = c;
        return ;
     }
     int m = (l + r) >> 1;
     if(p <= m) update(p,c,lson);
     else  update(p,c,rson);
     pushup(rt);
}

int querys(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        return sum[rt];
    }
    int m = (l + r) >> 1;
    int ret = 0;
    if(L <= m) ret += querys(L,R,lson);
    if(R > m) ret += querys(L,R,rson);
    return ret;
}

int querym(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        return maxx[rt];
    }
    int m = (l + r) >> 1;
    int ret = -0x3f3f3f3f;
    if(L <= m) ret = max(ret,querym(L,R,lson));
    if(R > m) ret = max(ret,querym(L,R,rson));
    return ret;
}

int asks(int x,int y){
    int sum = 0;
    int fx = top[x],fy = top[y];
    while(fx != fy){
        if(dep[fx] < dep[fy]){
            swap(fx,fy); swap(x,y);
        }
        sum += querys(tid[fx],tid[x],1,n,1);
        x = fa[fx]; fx = top[x];
    }
    if(dep[x] > dep[y]) swap(x,y);
    sum += querys(tid[x],tid[y],1,n,1);
    return sum;
}

int askm(int x,int y){
    int ans = -0x3f3f3f3f;
    int fx = top[x],fy = top[y];
    while(fx!=fy){
        if(dep[fx] < dep[fy]){
            swap(x,y);swap(fx,fy);
        }
        ans = max(ans,querym(tid[fx],tid[x],1,n,1));
        x = fa[fx]; fx = top[x];
    }
    if(dep[x] > dep[y]) swap(x,y);
    ans = max(ans,querym(tid[x],tid[y],1,n,1));
    return ans;
}

int main()
{
    int u,v,x,y;
    memset(son,-1,sizeof(son));
    scanf("%d",&n);
    cnt = 1;cnt1= 1;
    for(int i = 0;i < n- 1;i ++){
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    for(int i = 1;i <= n;i ++) scanf("%d",&a[i]);
    dfs1(1,0,1); dfs2(1,1);
    for(int i = 1;i <= n; i++){
        update(tid[i],a[i],1,n,1);
    }
    int q;
    char s[10];
    scanf("%d",&q);
    while(q--){
        scanf("%s",s);
        scanf("%d%d",&x,&y);
        if(s[1] == 'S') printf("%d\n",asks(x,y));
        else if(s[1]=='M') printf("%d\n",askm(x,y));
        else update(tid[x],y,1,n,1);
    }
    return 0;
}

 

posted @ 2018-04-17 19:27  冥想选手  阅读(152)  评论(0编辑  收藏  举报