关于我用树状数组做出了这道题...
查看原帖
关于我用树状数组做出了这道题...
677939
westernhan楼主2022/11/19 22:03

虽然用的是一种十分另类的树状数组。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdarg.h>
#include<ctype.h>
#define lowbit(e) (e&(-e))
typedef long long ll;
int n,ch,t,g,m;
ll p,c;
typedef struct
{
	ll sum,zhi,chen,lzy;
}hh;
hh a[100005];
void add(int w,int l)
{
	a[l].sum=w%p;a[l].chen=1;
	int r=lowbit(l);
	for (int x=1;x<r;x<<=1)
		a[l].sum=(a[l].sum+a[l-x].sum)%p;
}
void pushdown(int w)
{
	int up=lowbit(w);
	if (w>1)
	{
		for (int x=1;x<up;x<<=1)
		{
			int f=lowbit((w-x));
			a[w-x].sum=(a[w-x].sum*a[w].chen+a[w].lzy*f)%p;
			a[w-x].zhi=(a[w-x].zhi*a[w].chen+a[w].lzy)%p;
			a[w-x].lzy=(a[w-x].lzy*a[w].chen+a[w].lzy)%p;
			a[w-x].chen=(a[w-x].chen*a[w].chen)%p;
		}
		a[w].lzy=0;a[w].chen=1;
	}
}
ll cheng(ll w,int l,int r,int e)
{
	int left=e-lowbit(e)+1,up=lowbit(e);
	if (left>r||e<l)
	{
		return a[e].sum;
	}
	if (left>=l&&e<=r)
	{
		a[e].sum=(a[e].sum*w)%p;
		a[e].zhi=(a[e].zhi*w)%p;
		a[e].chen=(a[e].chen*w)%p;
		a[e].lzy=(a[e].lzy*w)%p;
		return a[e].sum;
	}
	pushdown(e);
	if (e>=l&&e<=r)
		a[e].zhi=(a[e].zhi*w)%p;
	a[e].sum=a[e].zhi;
	for (int x=1;x<up;x<<=1)
	{
		a[e].sum+=cheng(w,l,r,e-x);
		a[e].sum%=p;
	}
	return a[e].sum;
}
ll insert(ll w,int l,int r,int e)
{
	int left=e-lowbit(e)+1,up=lowbit(e);
	if (left>r||e<l)
	{
		return a[e].sum;
	}
	if (left>=l&&e<=r)
	{
		a[e].sum=(a[e].sum+(e-left+1)*w)%p;
		a[e].zhi=(a[e].zhi+w)%p;
		a[e].lzy=(a[e].lzy+w)%p;
		return a[e].sum;
	}
	pushdown(e);
	if (e>=l&&e<=r)
		a[e].zhi=(a[e].zhi+w)%p;
	a[e].sum=a[e].zhi;
	for (int x=1;x<up;x<<=1)
	{
		a[e].sum+=insert(w,l,r,e-x);
		a[e].sum%=p;
	}
	return a[e].sum;
}
ll query(int l,int r,int e)
{
	int left=e-lowbit(e)+1,up=lowbit(e);
	if (left>r||e<l)
	{
		return 0;
	}
	if (left>=l&&e<=r)
	{
		return a[e].sum;
	}
	pushdown(e);
	ll summ=0;
	if (e>=l&&e<=r)
		summ+=a[e].zhi;
	for (int x=1;x<up;x<<=1)
	{
		summ+=query(l,r,e-x);
		summ%=p;
	}
	return summ;
}
int main(void)
{
	scanf("%d%lld",&n,&p);
	for (int x=1;x<=n;x++)
	{
		scanf("%lld",&a[x].zhi);
		add(a[x].zhi,x);
	}
	scanf("%d",&m);
	for (int x=1;x<=m;x++)
	{
		scanf("%d%d%d",&ch,&t,&g);
		if (ch==1)
		{
			scanf("%lld",&c);
			for (int y=n;y>0;y-=lowbit(y))
				cheng(c,t,g,y);
		}
		else if (ch==2)
		{
			scanf("%lld",&c);
			for (int y=n;y>0;y-=lowbit(y))
				insert(c,t,g,y);
		}
		else if (ch==3)
		{
			ll summ=0;
			for (int y=n;y>0;y-=lowbit(y))
				summ=(summ+query(t,g,y))%p;
			printf("%lld\n",summ);
		}
	}
	return 0;
}

其实它只是运用了树状数组的lowbit来设结点,实质上是和线段树相似的。 详见https://www.luogu.com.cn/blog/westernhan/shu-zhuang-shuo-zu-di-xin-gou-xiang

2022/11/19 22:03
加载中...