BZOJ 1036 [ZJOI2008]树的统计Count (树链抛分)

本文介绍了一种高效解决树上节点权值查询及更新问题的方法——树链剖分线段树。通过将树剖分成链并利用线段树进行维护,实现了节点权值的快速更改和路径上节点权值的最大值及总和查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 11816   Solved: 4787
[ 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

HINT

Source

[ Submit][ Status][ Discuss]


        题目链接:点我!!!

        思路:树链抛分线段树本来是计算树上边的和,最大值等,只需要把线段树上记录的信息改为点就好了

        树链抛分推荐看神牛的博客,链接:http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html

      代码时间到:

#include<iostream>
#include<cstdio>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
typedef unsigned long long LLu;
typedef long long LL;
const int maxn=2*1e5+100;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int MOD = 1e9+7;
struct node{
	int sum,ma;
};
node A[maxn];
int B[maxn];//结点价值
int W[maxn];//结点对应线段树中位置
int head[maxn];
int Next[maxn];
int info[maxn];
int siz[maxn];
int son[maxn];
int top[maxn];
int dep[maxn];
int fa[maxn];
int tot,tow;
int n;
void init(){
	for(int i=0;i<maxn;i++){
		A[i].sum=A[i].ma=-INF;
		top[i]=i;

	}
	memset(head,-1,sizeof head);
	memset(dep,0,sizeof dep);
	memset(fa,-1,sizeof fa);
	tot=tow=0;
}
void add(int fr,int to){
	Next[tot]=head[fr];
	info[tot]=to;
	head[fr]=tot++;
}
void update(int a,int val,int l,int r,int rt){
	if(l==r){
		A[rt].ma=val;
		A[rt].sum=val;
		return ;
	}
	int mid=(l+r)>>1;
	if(a<=mid) update(a,val,lson);
	else update(a,val,rson);
	A[rt].sum=A[rt<<1].sum+A[rt<<1|1].sum;
	A[rt].ma=max(A[rt<<1].ma,A[rt<<1|1].ma);
}
int query(char c,int L,int R,int l,int r,int rt){
	if(L<=l&&R>=r){
		if(c=='m'){
			return A[rt].ma;
		}
		else return A[rt].sum;
	}
	if(c=='m'){
		int mid=(l+r)>>1;
		int ans=-INF;
		if(L<=mid) ans=max(ans,query(c,L,R,lson));
		if(R>mid) ans=max(ans,query(c,L,R,rson));
		return ans;
	}
	else{
		int mid=(l+r)>>1;
		int ans=0;
		if(L<=mid) ans+=query(c,L,R,lson);
		if(R>mid) ans+=query(c,L,R,rson);
		return ans;
	}
}
void dfs1(int a,int f){
	siz[a]=1;
	int k=-1;
	for(int i=head[a];i!=-1;i=Next[i]){
		if(info[i]==f) continue;
		dep[info[i]]=dep[a]+1;
		fa[info[i]]=a;
		dfs1(info[i],a);
		if(k==-1||siz[info[i]]>siz[k]) k=info[i];
		siz[a]+=siz[info[i]];
	}
	if(k!=-1) son[a]=k;
	else son[a]=-1;
}
void dfs2(int a,int f){
		W[a]=++tow;
		update(tow,B[a],1,n,1);
		if(son[a]!=-1){
			top[son[a]]=top[a];
			dfs2(son[a],a);
		}
	for(int i=head[a];i!=-1;i=Next[i]){
		if(info[i]==f||son[a]==info[i]) continue;
		dfs2(info[i],a);
	}
}
int find1(char c,int L,int R){
	if(c=='m'){
		int f1=top[L],f2=top[R],ans=-INF;
		while(f1!=f2){
//			printf("%d %d\n",f1,f2);
			if(dep[f1]>dep[f2]){
				swap(f1,f2);
				swap(L,R);
			}
			ans=max(ans,query('m',W[f2],W[R],1,n,1));
			R=fa[f2];
			f2=top[R];
		}
		if(L==R) return max(ans,B[L]);
		if(dep[L]>dep[R]) swap(L,R);
		return max(ans,query('m',W[L],W[R],1,n,1));
	}
	else{
		int f1=top[L],f2=top[R];
		int ans=0;
		while(f1!=f2){
			if(dep[f1]>dep[f2]){
				swap(f1,f2);
				swap(L,R);
			}
			ans+=query('s',W[f2],W[R],1,n,1);
			R=fa[f2];
			f2=top[R];
		}
		if(L==R) return ans+=B[L];
		if(dep[L]>dep[R]) swap(L,R);
		ans+=query('s',W[L],W[R],1,n,1);
		return ans;
	}
}
int main(){
	init();
	int i,j,k;
	scanf("%d",&n);
	for(i=1;i<n;i++){
		scanf("%d%d",&j,&k);
		add(j,k);
		add(k,j);
	}
	for(i=1;i<=n;i++){
		scanf("%d",&B[i]);
	}
	dfs1(1,-1);
//	cout<<n<<endl;
	dfs2(1,-1);
	int m;
	scanf("%d",&m);
	while(m--){
		char s[10];
		int a,b;
		scanf("%s%d%d",s,&a,&b);
		if(s[0]=='C'){
			B[a]=b;
			update(W[a],b,1,n,1);
		}
		else if(s[1]=='M'){
			printf("%d\n",find1('m',a,b));
		}
		else  if(s[1]=='S'){
			printf("%d\n",find1('s',a,b));
		}
	}
	return 0;
}


内容概要:该PPT详细介绍了企业架构设计的方法论,涵盖业务架构、数据架构、应用架构和技术架构四大核心模块。首先析了企业架构现状,包括业务、数据、应用和技术四大架构的内容和关系,明确了企业架构设计的重要性。接着,阐述了新版企业架构总体框架(CSG-EAF 2.0)的形成过程,强调其融合了传统架构设计(TOGAF)和领域驱动设计(DDD)的优势,以适应数字化转型需求。业务架构部通过梳理企业级和专业级价值流,细化业务能力、流程和对象,确保业务战略的有效落地。数据架构部则遵循五大原则,确保数据的准确、一致和高效使用。应用架构方面,提出了层解耦和服务化的设计原则,以提高灵活性和响应速度。最后,技术架构部围绕技术框架、组件、平台和部署节点进行了详细设计,确保技术架构的稳定性和扩展性。 适合人群:适用于具有一定企业架构设计经验的IT架构师、项目经理和业务析师,特别是那些希望深入了解如何将企业架构设计与数字化转型相结合的专业人士。 使用场景及目标:①帮助企业和组织梳理业务流程,优化业务能力,实现战略目标;②指导数据管理和应用开发,确保数据的一致性和应用的高效性;③为技术选型和系统部署提供科学依据,确保技术架构的稳定性和扩展性。 阅读建议:此资源内容详尽,涵盖企业架构设计的各个方面。建议读者在学习过程中,结合实际案例进行理解和实践,重点关注各架构模块之间的关联和协同,以便更好地应用于实际工作中。
资 源 简 介 独立(Independent Component Analysis,简称ICA)是近二十年来逐渐发展起来的一种盲信号离方法。它是一种统计方法,其目的是从由传感器收集到的混合信号中离相互独立的源信号,使得这些离出来的源信号之间尽可能独立。它在语音识别、电信和医学信号处理等信号处理方面有着广泛的应用,目前已成为盲信号处理,人工神经网络等研究领域中的一个研究热点。本文简要的阐述了ICA的发展、应用和现状,详细地论述了ICA的原理及实现过程,系统地介绍了目前几种主要ICA算法以及它们之间的内在联系, 详 情 说 明 独立(Independent Component Analysis,简称ICA)是近二十年来逐渐发展起来的一种盲信号离方法。它是一种统计方法,其目的是从由传感器收集到的混合信号中离相互独立的源信号,使得这些离出来的源信号之间尽可能独立。它在语音识别、电信和医学信号处理等信号处理方面有着广泛的应用,目前已成为盲信号处理,人工神经网络等研究领域中的一个研究热点。 本文简要的阐述了ICA的发展、应用和现状,详细地论述了ICA的原理及实现过程,系统地介绍了目前几种主要ICA算法以及它们之间的内在联系,在此基础上重点析了一种快速ICA实现算法一FastICA。物质的非线性荧光谱信号可以看成是由多个相互独立的源信号组合成的混合信号,而这些独立的源信号可以看成是光谱的特征信号。为了更好的了解光谱信号的特征,本文利用独立析的思想和方法,提出了利用FastICA算法提取光谱信号的特征的方案,并进行了详细的仿真实验。 此外,我们还进行了进一步的研究,探索了其他可能的ICA应用领域,如音乐信号处理、图像处理以及金融数据析等。通过在这些领域中的实验和应用,我们发现ICA在提取信号特征、降噪和信号离等方面具有广泛的潜力和应用前景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值