zoukankan      html  css  js  c++  java
  • BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count

    Time Limit: 10 Sec  Memory Limit: 162 MB

    Submit: 18937  Solved: 7731

    [Submit][Status][Discuss]

    Description

      一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. 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

    题解

    裸的树链剖分

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #define lson u<<1,l,mid
    #define rson u<<1|1,mid+1,r
    using namespace std;
    const int N=30005,inf=0x3f3f3f3f;
    int n,k=1,cnt,q;
    int head[N],w[N],fa[N],son[N],dep[N],tot[N],t[N],pre[N],top[N],sum[N<<2],mx[N<<2];
    struct edge{
    	int u,v,next;
    }e[N<<1];
    void addedge(int u,int v){
    	e[k]=(edge){u,v,head[u]};
    	head[u]=k++;
    }
    void insert(int u,int v){
    	addedge(u,v);
    	addedge(v,u);
    }
    void dfs1(int u){
    	int v;
    	dep[u]=dep[fa[u]]+1;
    	tot[u]=1;
    	for(int i=head[u];i;i=e[i].next){
    		v=e[i].v;
    		if(v==fa[u])continue;
    		fa[v]=u;
    		dfs1(v);
    		tot[u]+=tot[v];
    		if(!son[u]||tot[v]>tot[son[u]])son[u]=v;
    	}
    }
    void dfs2(int u,int f){
    	top[u]=f;
    	t[u]=++cnt;
    	pre[cnt]=u;
    	if(!son[u])return;
    	dfs2(son[u],f);
    	int v;
    	for(int i=head[u];i;i=e[i].next){
    		v=e[i].v;
    		if(v==son[u]||v==fa[u])continue;
    		dfs2(v,v);
    	}
    }
    void pushup(int u){
    	sum[u]=sum[u<<1]+sum[u<<1|1];
    	mx[u]=max(mx[u<<1],mx[u<<1|1]);
    }
    void build(int u,int l,int r){
    	if(l==r){
    		sum[u]=w[pre[l]];
    		mx[u]=w[pre[l]];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(lson);
    	build(rson);
    	pushup(u);
    }
    void update(int u,int l,int r,int a,int x){
    	if(l==r){
    		sum[u]=x;
    		mx[u]=x;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(a<=mid)update(lson,a,x);
    	else update(rson,a,x);
    	pushup(u);
    }
    int query_max(int u,int l,int r,int a,int b){
    	int ret=-inf;
    	if(l>=a&&r<=b)return mx[u];
    	int mid=(l+r)>>1;
    	if(a<=mid)ret=max(ret,query_max(lson,a,b));
    	if(b>mid)ret=max(ret,query_max(rson,a,b));
    	return ret;
    }
    int query_sum(int u,int l,int r,int a,int b){
    	int ret=0;
    	if(l>=a&&r<=b)return sum[u];
    	int mid=(l+r)>>1;
    	if(a<=mid)ret+=query_sum(lson,a,b);
    	if(b>mid)ret+=query_sum(rson,a,b);
    	return ret;
    }
    int get_max(int u,int v){
    	int ret=-inf;
    	int fu=top[u],fv=top[v];
    	while(fu!=fv){
    		if(dep[fu]<dep[fv]){
    			swap(u,v);
    			swap(fu,fv);
    		}
    		ret=max(ret,query_max(1,1,n,t[fu],t[u]));
    		u=fa[fu],fu=top[u];
    	}
    	if(dep[u]>dep[v])swap(u,v);
    	ret=max(ret,query_max(1,1,n,t[u],t[v]));
    	return ret;
    }
    int get_sum(int u,int v){
    	int ret=0;
    	int fu=top[u],fv=top[v];
    	while(fu!=fv){
    		if(dep[fu]<dep[fv]){
    			swap(u,v);
    			swap(fu,fv);
    		}
    		ret+=query_sum(1,1,n,t[fu],t[u]);
    		u=fa[fu],fu=top[u];
    	}
    	if(dep[u]>dep[v])swap(u,v);
    	ret+=query_sum(1,1,n,t[u],t[v]);
    	return ret;
    }
    int main(){
    	scanf("%d",&n);
    	int a,b;
    	for(int i=1;i<=n-1;i++){
    		scanf("%d%d",&a,&b);
    		insert(a,b);
    	}
    	for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    	dfs1(1);
    	dfs2(1,1);
    	build(1,1,n);
    	scanf("%d",&q);
    	int u,v;
    	char ch[10];
    	for(int i=1;i<=q;i++){
    		scanf("%s%d%d",ch,&u,&v);
    		if(ch[1]=='H')update(1,1,n,t[u],v);
    		else if(ch[1]=='M')printf("%d
    ",get_max(u,v));
    		else if(ch[1]=='S')printf("%d
    ",get_sum(u,v));
    	}
    	return 0;
    }
  • 相关阅读:
    进程与线程的区别与联系
    任务、进程、线程
    类、对象、方法、实例方法、类方法
    java 泛型详解
    Java总结篇系列:Java泛型
    html+css+js 实现自动滑动轮播图
    第三篇web前端面试自我介绍(刚毕业的菜鸟)
    怎么写网站的需求文档
    在phpStudy怎么配置虚拟地址
    第二篇web前端面试自我介绍(刚毕业的菜鸟)
  • 原文地址:https://www.cnblogs.com/chezhongyang/p/7681784.html
Copyright © 2011-2022 走看看