经典的线段树区间更新题目
对于每次更新 分为除法标记和乘法标记
如果乘法标记不为0
那么我进行除法标记是将乘法标记减一即可
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const long long mod=1000000007;
vector<long long> factor[100015];
long long a[100005];
long long cnt=0;
long long prime[2015];
long long vis[2010];
struct node
{
long long l;
long long r;
long long tag1;
long long tag2;
} tree[401010];
long long divi,mul;
long long quick_pow(long long a,long long b)
{
long long x;
x=1;
a=a%mod;
while(b)
{
if(b%2==1) x=(x*a)%mod;
b/=2;
a=(a*a)%mod;
}
return x;
}
long long ans=1;
void push_down(long long root)
{
if(tree[root].l!=tree[root].r)
{
if(tree[root*2].tag1>=tree[root].tag2) tree[root*2].tag1-=tree[root].tag2;
else
{
tree[root*2].tag2+=(tree[root].tag2-tree[root*2].tag1),tree[root*2].tag1=0;
}
if(tree[root*2+1].tag1>=tree[root].tag2) tree[root*2+1].tag1-=tree[root].tag2;
else
{
tree[root*2+1].tag2+=(tree[root].tag2-tree[root*2+1].tag1),tree[root*2+1].tag1=0;
}
tree[root*2].tag1+=tree[root].tag1;
tree[root*2+1].tag1+=tree[root].tag1;
tree[root].tag1=0;
tree[root].tag2=0;
}
}
void init(int n)
{
for(int i = 2; i <= n; i++)if(!vis[i])
{
prime[++cnt] = i;
for(ll j = (ll)i * i; j <= n; j += i)vis[j] = 1;
}
}
void build(long long l,long long r,long long root)
{
tree[root].l=l;
tree[root].r=r;
tree[root].tag1=0;
tree[root].tag2=0;
if(l==r) return ;
long long mid=(l+r)/2;
build(l,mid,root*2);
build(mid+1,r,root*2+1);
}
void qurey(long long k,long long root)
{
if(tree[root].l==tree[root].r&&tree[root].l==k)
{
divi=tree[root].tag2;
mul=tree[root].tag1;
return ;
}
if(tree[root].tag1||tree[root].tag2) push_down(root);
long long mid=(tree[root].l+tree[root].r)/2;
if(k<=mid) qurey(k,root*2);
else qurey(k,root*2+1);
}
void update(long long l,long long r,long long root,long long op)//l r ¡ä¨²¡À¨ª ?¨´¨°a¡¤??¨º¦Ì?????
{
if(tree[root].l==l&&tree[root].r==r)//¨¨?1?¡ã¨¹o??¨²?????¨²2?
{
if(op==1)
{
tree[root].tag1++;
}
else
{
if(tree[root].tag1>0) tree[root].tag1--;
else tree[root].tag2++;
}
return ;
}
if(tree[root].tag1||tree[root].tag2) push_down(root);
long long mid=(tree[root].l+tree[root].r)/2;
if(l>mid) update(l,r,root*2+1,op);
else if(r<=mid) update(l,r,root*2,op);
else {
update(l,mid,root<<1,op);
update(mid+1,r,root<<1|1,op);
}
}
int main()
{
memset(vis,0,sizeof(vis));
init(1000);
long long n,m;
scanf("%lld%lld",&n,&m);
for(long long i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
long long tmp=a[i];
for(long long j=1; prime[j]*prime[j]<=tmp&&j<=cnt; j++)
{
while(tmp%prime[j]==0)
{
factor[i].push_back(prime[j]);
tmp/=prime[j];
}
}
if(tmp!=1) factor[i].push_back(tmp);
}
build(1,n,1);
while(m--)
{
long long op;
scanf("%lld",&op);
if(op==1||op==2)
{
long long tmp1,tmp2;
scanf("%lld%lld",&tmp1,&tmp2);
update(tmp1,tmp2,1,op);
}
else
{
long long cao;
scanf("%lld",&cao);
qurey(cao,1);
ans=1;
if(divi>=factor[cao].size())
{
printf("1
");
}
else
{
for(long long i=divi; i<factor[cao].size(); i++)
{
ans=(ans*factor[cao][i]);
}
ans=ans*quick_pow(factor[cao][divi],mul)%mod;
printf("%lld
",ans);
}
}
}
}