One-X

这里肯定考虑每个点作为lca对答案的贡献

考虑点p,所代表的区间长度为l,那么其左右两个子树的叶子节点一定至少选一个,即贡献为p×(2l21)×(2l21),其中l2l2分别为左右子树所代表的区间长度,减一是因为要去掉一个叶子都不选的情况

然后有一个结论,线段树每层的不同区间的长度至多相差一

考虑用数学归纳法证明,假设对第i层,代表长度为ll1,那么第i+1层的长度就是l2,l2,l12,l12,根据l的奇偶讨论即可

那么我们储存每一层的区间的长度,以及每一种区间长度的区间的个数,以及对应的节点的编号和

举个例子,假设线段树的根节点的长度是5,处于第一层,那么第三层就有四个节点,分别为(4,[1,2]),(5,[3,3]),(6,[4,4]),(7,[5,5]),我们就统计长度为2的区间有一个,编号和为4;长度为1的区间有三个,编号和为18

那么我们推导下一层的对应信息,就先算出下一层的长度以及对应的区间个数,那么编号和显然一个乘以2另一个乘以2再加上区间的个数,可以自己推导一下

这里的推导也启示我们,不用非要记录最终的结果,我们记录结果的每个因子也是可以的

时间复杂度为O(log2n)

代码一定也看一下,用了map的迭代器

#include<bits/stdc++.h>
#define ll long long
#define ULL unsigned long long
using namespace std;
const int p=998244353;
ll n;
map<ll,pair<int,int> > mp[100];//mp[i][l]表示第i层区间长度为l的信息
//mp[i][l].first表示长度为l的区间的编号和
//mp[i][l].second表示长度为l的区间的个数
//之所以要用map,是因为区间长度在贡献式子里面为指数部分,不能随意取模 
ll quickpow(ll a,ll b)
{
	ll res=1;
	while(b)
	{
		if(b&1) res=(res*a)%p;
		a=(a*a)%p;
		b>>=1;
	}
	return res;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int res=0;
		scanf("%lld",&n);
		int lg=__lg(n)+3;
		for(int i=1;i<=lg;i++)
		mp[i].clear();
		mp[1][n]=make_pair(1,1);
		for(int i=1;i<=lg;i++)
		for(map<ll,pair<int,int> >::iterator it=mp[i].begin();it!=mp[i].end();it++)
		{
			pair<ll,pair<int,int> > u=*it;
			if(u.first==1)
			{
				res=(res+u.second.first)%p;
				continue;
			}
			ll l=(u.first+1)/2,r=u.first-l;
			res=(res+u.second.first*(quickpow(2,l)-1)%p*(quickpow(2,r)-1)%p)%p;
			mp[i+1][l].first=(mp[i+1][l].first+u.second.first*2%p)%p;
			mp[i+1][l].second=(mp[i+1][l].second+u.second.second)%p;
			mp[i+1][r].first=(mp[i+1][r].first+(u.second.first*2%p+u.second.second)%p)%p;
			mp[i+1][r].second=(mp[i+1][r].second+u.second.second)%p;
		}
		printf("%d\n",res);
	}
	return 0;
}

update 2024.7.12

想到一种新的做法,对于完全二叉树,我们显然可以通过按层统计来得到答案

对于每一层,我们可以算出编号和,而每个节点所代表的区间长度都是一样的,所以可以直接计算

对于非完全二叉树,可以知道左右子树一定有一个是完全二叉树,对于完全二叉树的部分采用上述做法,非完全二叉树部分递归计算即可,时间复杂度仍然是O(log2n)

想到这种做法主要还是从考虑贡献+特殊情况入手

update 2024.7.29

上面想出来的新做法是错的,线段树建的树不一定是按照逐个增加节点的方法建的,如下

正确思路的原因是,同一长度的节点,建出的树的形态是一样的,可以直接利用长度统计

posted @   最爱丁珰  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示