JZOJ3360/BZOJ3757. 【NOI2013模拟】苹果树 (Standard IO)

博客围绕神犇家苹果树上苹果颜色计数问题展开。该问题需计算从一个苹果到另一个苹果路径上不同颜色的种数,还需考虑色盲情况。题目离线,采用树上莫队方法求解,可维护栈和时间戳,同时要注意特定颜色情况。

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

神犇家门口种了一棵苹果树。苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条。由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色。我们用一个1到N之间的正整数来表示一种颜色。树上一共有N个苹果。每个苹果都被编了号码,号码为一个1到N之间的正整数。我们用0代表树根。只会有一个苹果直接连到树根。
有许许多多的人来神犇家里膜拜神犇。可神犇可不是随便就能膜拜的。前来膜拜神犇的人需要正确回答一个问题,才能进屋膜拜神犇。这个问题就是,从树上编号为N的苹果出发,由树枝走到编号为N的苹果,路径上经过的苹果一共有多少种不同的颜色(包括苹果u和苹果v的颜色)?不过神犇注意到,有些来膜拜的人患有色盲症。具体地说,一个人可能会认为颜色a就是颜色b,那么他们在数苹果的颜色时,如果既出现了颜色a的苹果,又出现了颜色b的苹果,这个人只会算入颜色b,而不会把颜色a算进来。
神犇是一个好人,他不会强人所难,也就会接受由于色盲症导致的答案错误(当然答案在色盲环境下也必须是正确的)。不过这样神犇也就要更改他原先数颜色的程序了。虽然这对于神犇来说是小菜一碟,但是他想考验一下你。你能替神犇完成这项任务吗?
Input输入第一行为两个整数N和M,分别代表树上苹果的个数和前来膜拜的人数。
接下来的一行包含N个数,第i个数代表编号为i的苹果的颜色coli。
接下来有N行,每行包含两个数x和y,代表有一根树枝连接了苹果x和y(或者根和一个苹果)。
接下来有M行,每行包含四个整数u、v、a和b,代表这个人要数苹果u到苹果v的颜色种数,同时这个人认为颜色a就是颜色b。如果a=b=0,则代表这个人没有患色盲症。
Output
输出一共M行,每行仅包含一个整数,代表这个人应该数出的颜色种数。
Sample Input
5 3
1 1 3 3 2
0 1
1 2
1 3
2 4
3 5
1 4 0 0
1 4 1 3
1 4 1 2
Sample Output
2
1
2

这道题看起来不好做,要用一些莫名其妙的东西,给人第一感是树剖但我不会打
发现题目离线,考虑树上莫队。
可以维护一个栈,当栈的新增长度len大于莫队分块bg的块大小,栈弹出bg个数,让这些数在同一个块里即可。
可以维护时间戳当快排第二关键字
接着就是一些常规操作了
注意:可能会出现color[a]=color[b]&&color[a]>0的情况。
code:(在JZOJ上跑1300ms,时限为2000ms)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int block[100001],dfn[100001],sta[100001];
int f[200001][4],q[200001],ans[200001],co[200001];
int b[200001][17],mi[200001],num[200001],dep[200001];
bool a[100001];
struct node{
	int x,y,a,b,id;
}que[100005];
int i,j,k,m,n,o,p,l,s,t,sum,now,tot,root,top,bg,g;
void insert(int x,int y)
{
	f[++t][1]=y,f[t][2]=q[x],q[x]=t;
}
int dg(int t,int fa)
{
	int size=0;
	dfn[t]=++tot;
	for (int k=q[t];k;k=f[k][2])
	{
		if (f[k][1]==fa) continue;b[f[k][1]][0]=t,dep[f[k][1]]=dep[t]+1;
		size+=dg(f[k][1],t);
		if (size>=bg)
		{
			g++;
			for (int k=1;k<=size;k++) block[sta[top--]]=g;
			size=0;
		}
	}
	sta[++top]=t;
	return size+1;
}
bool cmp(node a,node b)
{
	return (block[a.x]==block[b.x]?dfn[a.y]<dfn[b.y]:block[a.x]<block[b.x]);
}
int getlca(int x,int y)
{
	if (dep[x]<dep[y]) swap(x,y);
	int k=dep[x]-dep[y];
	for (int i=16;i>=0;i--)
	{
		if (k>=mi[i]) k-=mi[i],x=b[x][i];	
	}	
	if (x==y) return x;
	for (int i=16;i>=0;i--)
	{
		if (b[x][i]!=b[y][i]) x=b[x][i],y=b[y][i];
	}
	return b[x][0];
} 
void work(int x)
{
	if (!a[x]) now+=(++num[co[x]]==1);
	else now-=(--num[co[x]]==0);
	a[x]^=1;
}
void change(int x,int y)
{
	while (x!=y)
	{
		if (dep[x]>dep[y]) work(x),x=b[x][0];
		else work(y),y=b[y][0]; 
	}
}
int main()
{
	freopen("Pique.in","r",stdin);
	freopen("Pique.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (i=1;i<=n;i++) scanf("%d",&co[i]);
	for (i=1;i<=n;i++)
	{
		scanf("%d%d",&o,&p);
		if (!(o*p)) root=o+p;
		else insert(o,p),insert(p,o);
	}
	bg=sqrt(n);dg(root,0);g++;
	while (top) block[sta[top--]]=g;mi[0]=1;
	for (i=1;i<=16;i++)
	{
		mi[i]=mi[i-1]*2;
		for (j=1;j<=n;j++) b[j][i]=b[b[j][i-1]][i-1];
	}
	for (i=1;i<=m;i++) scanf("%d%d%d%d",&que[i].x,&que[i].y,&que[i].a,&que[i].b),que[i].id=i;
	sort(que+1,que+m+1,cmp);
	int x=root,y=root;now=0;
	for (i=1;i<=m;i++)
	{
		if (x!=que[i].x) change(x,que[i].x),x=que[i].x;
		if (y!=que[i].y) change(y,que[i].y),y=que[i].y;
		k=getlca(x,y);work(k);
		if ((que[i].a==que[i].b)||(!(num[que[i].a]*num[que[i].b]))) ans[que[i].id]=now;
		else ans[que[i].id]=now-1;work(k);
	}
	for (i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}
内容概要:本文详细探讨了基于MATLAB/SIMULINK的多载波无线通信系统仿真及性能分析,重点研究了以OFDM为代表的多载波技术。文章首先介绍了OFDM的基本原理和系统组成,随后通过仿真平台分析了不同调制方式的抗干扰性能、信道估计算法对系统性能的影响以及同步技术的实现与分析。文中提供了详细的MATLAB代码实现,涵盖OFDM系统的基本仿真、信道估计算法比较、同步算法实现和不同调制方式的性能比较。此外,还讨论了信道特征、OFDM关键技术、信道估计、同步技术和系统级仿真架构,并提出了未来的改进方向,如深度学习增强、混合波形设计和硬件加速方案。; 适合人群:具备无线通信基础知识,尤其是对OFDM技术有一定了解的研究人员和技术人员;从事无线通信系统设计与开发的工程师;高校通信工程专业的高年级本科生和研究生。; 使用场景及目标:①理解OFDM系统的工作原理及其在多径信道环境下的性能表现;②掌握MATLAB/SIMULINK在无线通信系统仿真中的应用;③评估不同调制方式、信道估计算法和同步算法的优劣;④为实际OFDM系统的设计和优化提供理论依据和技术支持。; 其他说明:本文不仅提供了详细的理论分析,还附带了大量的MATLAB代码示例,便于读者动手实践。建议读者在学习过程中结合代码进行调试和实验,以加深对OFDM技术的理解。此外,文中还涉及了一些最新的研究方向和技术趋势,如AI增强和毫米波通信,为读者提供了更广阔的视野。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值