E、小花梨的数组(线段树)

经典的线段树区间更新题目

对于每次更新 分为除法标记和乘法标记

如果乘法标记不为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);
            }
        }
    }
}
原文地址:https://www.cnblogs.com/caowenbo/p/11852256.html