ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【洛谷4738】[CERC2017] Cumulative Code(Meet in Middle)

2021-06-17 07:33:23  阅读:194  来源: 互联网

标签:CI Code 洛谷 4738 ct fg nw 节点 define


点此看题面

  • 一棵\(n\)层的满二叉树,从上往下、从左往右编号,设\(p\)为它的\(prufer\)序列。
  • \(q\)次询问,每次给出\(a,d,m\),求\(\sum_{i=1}^mp_{a+(i-1)\times d}\)。
  • \(n\le30,q\le300\)

暴力搜索

如果当前点有父节点,那么我们会先把左子树删完,再把右子树删完,最后删去当前点。

如果当前点没有父节点,那么我们会先把左子树删完,然后就删去当前点,最后把右子树删完。

因此可以写一个暴搜,记录当前点编号以及是否有父节点即可。

折半思想

由于这是一棵满二叉树,子树的形态只和深度有关,容易发现\(prufer\)序列的每一项都可以写成一个关于子树根节点编号的一次函数\(k_ix+b_i\)。

我们预处理出第\(\lfloor\frac n2\rfloor+1\)层节点子树内的\(prufer\)序列(注意,根据是否有父节点,会分为两种)。

每次询问时事先预处理出\(k_i,b_i\)隔\(d\)项的前缀和,然后在前\(\lfloor\frac n2\rfloor\)层中暴搜,一旦进入第\(\lfloor\frac n2\rfloor+1\)层就利用预处理出的前缀和以及当前点编号求出答案。

代码:\(O(q2^{\frac n2})\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 30
#define S 65536
#define LL long long
using namespace std;
int n,a,d,m,ct,k[2][S+5],b[2][S+5];LL K[2][S+5],B[2][S+5];
I void Init(CI ty,CI x,CI y,CI p,CI fg)//预处理
{
	if(p>n) return;//超出深度
	if(fg) Init(ty,x<<1,y<<1,p+1,0),k[ty][++ct]=x<<1,b[ty][ct]=y<<1|1,Init(ty,x<<1,y<<1|1,p+1,1);//左中右
	else Init(ty,x<<1,y<<1,p+1,0),Init(ty,x<<1,y<<1|1,p+1,0),k[ty][++ct]=x>>1,b[ty][ct]=y>>1;//左右中
}
I LL Calc(CI x,CI nw,CI fg)//计算子树根节点编号为x,之前访问过总点数为nw时的答案
{
	RI l=max(nw+1,a),r=min(nw+ct,a+(m-1)*d);l+=(a%d-l%d+d)%d,r-=(r%d-a%d+d)%d;if(l>r) return 0;//把l,r调成与a同余
	return l-=nw,r-=nw,K[fg][r]*x+B[fg][r]-(l>d?K[fg][l-d]*x+B[fg][l-d]:0)+(!fg&&r==ct?x>>1:0);//利用隔d前缀和计算答案,特判根节点父节点的贡献
}
int nw;LL ans;I void dfs(CI x,CI p,CI fg)//在前n/2层暴搜
{
	if(p>n/2) return (void)(ans+=Calc(x,nw,fg),nw+=ct);//达到第n/2+1层,利用预处理结果计算答案
	if(fg) dfs(x<<1,p+1,0),++nw>=a&&!((nw-a)%d)&&(nw-a)/d<m&&(ans+=x<<1|1),dfs(x<<1|1,p+1,1);//左中右
	else dfs(x<<1,p+1,0),dfs(x<<1|1,p+1,0),++nw>=a&&!((nw-a)%d)&&(nw-a)/d<m&&(ans+=x>>1);//左右中
}
int main()
{
	RI Qt,i,j,x,y,z;scanf("%d%d",&n,&Qt),Init(0,1,0,n/2+1,0),ct=0,Init(1,1,0,n/2+1,1);W(Qt--)
	{
		for(scanf("%d%d%d",&a,&d,&m),i=1;i<=ct;++i)
			for(j=0;j<=1;++j) K[j][i]=(i>d?K[j][i-d]:0)+k[j][i],B[j][i]=(i>d?B[j][i-d]:0)+b[j][i];//隔d前缀和
		nw=ans=0,dfs(1,1,1),printf("%lld\n",ans);
	}return 0;
}

标签:CI,Code,洛谷,4738,ct,fg,nw,节点,define
来源: https://www.cnblogs.com/chenxiaoran666/p/Luogu4738.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有