求助,线段树与树状数组,感谢每位大佬
  • 板块题目总版
  • 楼主渡鸦2007
  • 当前回复5
  • 已保存回复5
  • 发布时间2021/5/3 23:57
  • 上次更新2023/11/4 23:46:07
查看原帖
求助,线段树与树状数组,感谢每位大佬
385748
渡鸦2007楼主2021/5/3 23:57

感谢每位肯抽出自己宝贵时间帮助我的大佬

题面:

给定一段长度为N的序列,编号从1开始,和如下三种操作。

1 a b:将位置a的数修改为b

2 a b:询问[a,b]区间内所有数的和,mod 10007。

3 a b:询问[a,b]区间内所有数的积,mod 10007。

第一行一个整数N,表示序列长度。

接下来一行N个用空格隔开的整数,表示初始的序列。

接下来一个整数M,表示操作的个数。

接下来M行每行三个整数,表示操作。

【样例输入】
3
2 3 3
3
2 1 2
1 1 1
3 1 2
【样例输出】
5
3

我的代码,思路是和用树状数组,乘积用线段树

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define re register
int read()
{
	register int ans=0;
	char ch;
	bool flag=0;
	while(1)
	{
		ch=getchar();
		if (ch>='0'&&ch<='9')
		{
			break;
		}
		if (ch=='-')
		{
		   flag=1;
		}
	}
	while(1)
	{
		ans=ans*10+ch-'0';
		ch=getchar();
		if (ch<'0'||ch>'9')
		{
			break;
		}
	}
	if (flag==1)
	{
	   ans*=-1;
	}
	return ans;
}
int lowbit(int num)
{
	return num & (~num+1); 
}
int n;
int sum[1000100];//树状数组
void upset1(int num,int where)//树状数组更新
{
	while (where<=n)
	{
		sum[where]+=num;
		sum[where]%=10007;
		where+=lowbit(where);
	}
}
int gs(int where)//树状数组求和
{
	int ans=0;
	while (where>0)
	{
		ans+=sum[where];
		ans%=10007;
		where-=lowbit(where);
	}
	return ans;
}
int xdt[400100];//线段树
void upset(int id,int where,int l,int r,int num)//线段树更新
{
	if (r<where||l>where)
	{
		return;
	}
	if (l==where&&r==where)
	{
		xdt[id]=num;
		return;
	}
	int mid=(l+r)>>1;
	upset(id*2,where,l,mid,num);
	upset(id*2+1,where,mid+1,r,num);
	xdt[id]=xdt[id*2]*xdt[id*2+1]%10007;
}
long long ask(int id,int nl,int nr,int l,int r)//线段树求乘积
{
	if (nl>r||nr<l)
	{
		return 1;
	}
	if (nl>=l&&nr<=r)
	{
		return xdt[id]%10007;
	}
	int mid=(nl+nr)>>1;
	long long ans=1;
	ans*=ask(id*2,nl,mid,l,r);
	ans%=10007;
	ans*=ask(id*2+1,mid+1,nr,l,r);
	return ans%10007;
}
int main()
{
	//freopen("segtree.in","r",stdin);
	//freopen("segtree.out","w",stdout);
	n=read();
	for (re int i=1;i<=n;++i)
	{
		int t=read();
		upset1(t,i); //树状数组初始
		upset(1,i,1,n,t);//线段树初始
	}
	int m;m=read();
	for (re int i=1;i<=m;++i)
	{
		int k,a,b;k=read();a=read();b=read();
		if (k==1)
		{
			upset1(b-sum[a],a);//树状数组
			upset(1,a,1,n,b);//线段树
		}
		if (k==2)
		{
			int ans=gs(b)-gs(a-1);
			if (ans<0)
			{
				ans+=10007;
			}
			printf("%d\n",ans);
		}
		if (k==3)
		{
			long long ans=ask(1,1,n,a,b);ans%=10007;
			printf("%lld\n",ans);
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}
2021/5/3 23:57
加载中...