zoukankan      html  css  js  c++  java
  • [ZJOI2008]树的统计

    洛咕

    题意:一棵树上有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本身

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        int s=0,w=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    int n,Q,ans1,ans2;char s[10];
    int val[30005],maxn[120005],sum[120005];
    int size[30005],deep[30005],fa[30005],son[30005];
    int top[30005],seg[30005],rev[120005];
    int tot,head[30005],nxt[60005],to[60005];
    void add(int a,int b){
        nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
        nxt[++tot]=head[b];head[b]=tot;to[tot]=a;
    }
    void dfs1(int u){
        size[u]=1;
        for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];
    		if(v==fa[u])continue;
    		deep[v]=deep[u]+1;
    		fa[v]=u;
    		dfs1(v);
    		size[u]+=size[v];
    		if(size[son[u]]<size[v])son[u]=v;
        }
    }
    void dfs2(int u){
        if(son[u]){
    		top[son[u]]=top[u];
    		seg[son[u]]=++seg[0];
    		rev[seg[0]]=son[u];
    		dfs2(son[u]);
        }
        for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];
    		if(!top[v]){
    	    	top[v]=v;
    	    	seg[v]=++seg[0];
    	    	rev[seg[0]]=v;
    	    	dfs2(v);
    		}
        }
    }
    void build(int k,int l,int r){
        if(l==r){
    		maxn[k]=sum[k]=val[rev[l]];
    		return;
        }
        int mid=(l+r)>>1;
        build(k<<1,l,mid);build((k<<1)|1,mid+1,r);
        sum[k]=sum[k<<1]+sum[(k<<1)|1];
        maxn[k]=max(maxn[k<<1],maxn[(k<<1)|1]);
        return;
    }
    void change(int k,int l,int r,int val,int pos){
        if(pos>r||pos<l)return;
        if(l==r&&l==pos){
    		sum[k]=maxn[k]=val;
    		return;
        }
        int mid=(l+r)>>1;
        if(mid>=pos)change(k<<1,l,mid,val,pos);
        if(mid+1<=pos)change((k<<1)|1,mid+1,r,val,pos);
        sum[k]=sum[k<<1]+sum[(k<<1)|1];
        maxn[k]=max(maxn[k<<1],maxn[(k<<1)|1]);
    }
    void query(int k,int l,int r,int L,int R){
        if(L>r||R<l)return;
        if(L<=l&&r<=R){
    		ans1=max(ans1,maxn[k]);
    		ans2+=sum[k];
    		return;
        }
        int mid=(l+r)>>1;
        if(mid>=L)query(k<<1,l,mid,L,R);
        if(mid+1<=R)query((k<<1)|1,mid+1,r,L,R);
    }
    void ask(int x,int y){
        while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]])swap(x,y);
    		query(1,1,seg[0],seg[top[x]],seg[x]);
    		x=fa[top[x]];
        }
        if(deep[x]>deep[y])swap(x,y);
        query(1,1,seg[0],seg[x],seg[y]);
    }
    int main(){
        n=read();
        for(int i=1;i<n;i++)add(read(),read());
        for(int i=1;i<=n;i++)val[i]=read();
        top[1]=seg[0]=seg[1]=rev[1]=1;deep[1]=1;
        dfs1(1);dfs2(1);build(1,1,seg[0]);
        Q=read();
        while(Q--){
    		scanf("%s",s);
    		int a=read(),b=read();
    		if(s[0]=='C')change(1,1,seg[0],b,seg[a]);
    		else{
    	    	ans1=-1e9,ans2=0;
    	    	ask(a,b);
    	    	if(s[1]=='M')printf("%d
    ",ans1);
    	    	else printf("%d
    ",ans2);
    		}
        }
        return 0;
    }
    
    
  • 相关阅读:
    Shell bash脚本查询Mysql并简单处理查询结果
    Caused by: java.lang.ClassNotFoundException: org.apache.flink.streaming.api.scala.StreamExecutionEnv
    Flink的部署方式
    Flink线上环境搭建
    数仓及数据治理相关
    Hive动态分区详解及注意的问题
    lateral view explode行转列的简单使用
    MachineLearning
    Linux 查看CPU信息,机器型号,内存等信息
    redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect time out
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10561614.html
Copyright © 2011-2022 走看看