zoukankan      html  css  js  c++  java
  • 树的统计 树链剖分

    Code:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=30000+5;
    int head[maxn],nex[maxn*2],to[maxn*2];               
    int dep[maxn],siz[maxn],son[maxn],p[maxn],top[maxn];
    int A[maxn],maxv[maxn*4+3], val[maxn];  
    int val2[maxn];                            
    ll sumv[maxn*4+3];    
    int _max;                
    int cnt,n,cnt2;
    void addedge(int u,int v)
    {
    	nex[++cnt]=head[u];
    	head[u]=cnt,to[cnt]=v;
    }
    void dfs1(int u,int fa,int cur){
    	p[u]=fa,dep[u]=cur,siz[u]=1;
        for(int i=head[u];i;i=nex[i])
    	{
    		int v=to[i];
    		if(v!=fa)
    		{
    			dfs1(v,u,cur+1);
    			siz[u]+=siz[v];
    			if(son[u]==-1||siz[v]>siz[son[u]])son[u]=v;
    		}
    	}
    }
    void dfs2(int u,int tp)
    {
    	top[u]=tp,A[u]=++cnt2;
    	if(son[u]>0)dfs2(son[u],tp);
    	for(int i=head[u];i;i=nex[i])
    	{
    		int v=to[i];
    		if(v!=p[u]&&v!=son[u])dfs2(v,v);
    	}
    }
    void build_tree(int L,int R,int o,int arr[])
    {
    	if(L==R){
    		sumv[o]=maxv[o]=arr[L];
    		return;
    	}
    	int mid=(L+R)/2;
    	build_tree(L,mid,o*2,arr);
    	build_tree(mid+1,R,o*2+1,arr);
    	sumv[o]=sumv[o*2]+sumv[o*2+1];
    	maxv[o]=max(maxv[o*2],maxv[o*2+1]);
    }
    void update(int l,int k,int L,int R,int o)
    {
    	if(L==R)
    	{
           sumv[o]=maxv[o]=k;
           return;
    	}
    	int mid=(L+R)/2;
    	if(l<=mid)update(l,k,L,mid,o*2);
    	else update(l,k,mid+1,R,o*2+1);
    	sumv[o]=sumv[o*2]+sumv[o*2+1];
    	maxv[o]=max(maxv[o*2],maxv[o*2+1]);
    }
    ll query(int l,int r,int L,int R,int o)
    {
    	if(l<=L&&r>=R)
    	{
    		_max=max(_max,maxv[o]);
    		return sumv[o];
    	}
    	int mid=(L+R)/2;
    	ll ret=0;
    	if(l<=mid)ret+=query(l,r,L,mid,o*2);
    	if(r>mid)ret+=query(l,r,mid+1,R,o*2+1);
    	return ret;
    }
    ll lca(int x,int y)    
    {
    	_max=-300000;
    	ll ret=0;
    	while(top[x]!=top[y])
    	{
             if(dep[top[x]]<dep[top[y]]){ret+=query(A[top[y]],A[y],1,n,1);y=p[top[y]];}
             else {ret+=query(A[top[x]],A[x],1,n,1);x=p[top[x]];}
    	}
    	if(dep[x]<dep[y])ret+=query(A[x],A[y],1,n,1);
    	else ret+=query(A[y],A[x],1,n,1);
    	return ret;
    }
    int main()
    {
    	memset(son,-1,sizeof(son));
    	scanf("%d",&n);
    	for(int i=1;i<n;++i){
    		int a,b;
    		scanf("%d%d",&a,&b);
    		addedge(a,b);
    		addedge(b,a);
    	}
    	for(int i=1;i<=n;++i)scanf("%d",&val[i]);
    	dfs1(1,-1,1);                             //以一为根
        dfs2(1,1);
        for(int i=1;i<=n;++i)val2[A[i]]=val[i];
    	build_tree(1,n,1,val2);                    //建树
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		char S[20];
    		scanf("%s",S);
    		if(S[0]=='C'){
    			int u,t;
    			scanf("%d%d",&u,&t);
    			update(A[u],t,1,n,1);
    		}
    		if(S[1]=='M'){
                int x,y;
                scanf("%d%d",&x,&y);
                lca(x,y);
                printf("%d
    ",_max);
    		}
    		if(S[1]=='S')
    		{
    			int x,y;
    			scanf("%d%d",&x,&y);
    			printf("%lld
    ",lca(x,y));
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    周总结6
    河北省重大需求征集系统每日进度8
    《代码整洁之道》读书笔记3
    周总结5
    河北省重大需求征集系统每日进度7
    mybatis 关联查询多个类型相同对象
    thymeleaf 接受字符串类型model值作为js方法参数报错500
    毕业设计(2.17-2.23)周工作计划
    毕业设计记录——2.16
    毕业设计记录——2.15
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845095.html
Copyright © 2011-2022 走看看