感谢每位肯抽出自己宝贵时间帮助我的大佬
给定一段长度为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;
}