• [线段树]小花梨的数组


    题目描述

    小花梨得到了一个长度为n的数组a,现在要对它进行三种操作:
    ⚫1 l r对所有的i∈[l,r],a[i]=a[i]∗minprime(a[i])
    ⚫2 l r对所有的i∈[l,r],a[i]=a[i]/minprime(a[i])
    ⚫3 x
    求a[x]的值

    现在给出初始数组a,对其进行m次操作,对于第三种操作输出结果。

    输入

    第一行输入两个正整数n,m,表示数组的长度以及操作次数(1≤n,m≤100000)
    第二行输入n个正整数表示数组a(1≤ai≤1000000)
    接下来m行表示m次操作,每行输入格式为"1 l r"或者"2 l r",或者"3 x",对应上述三种操作。1≤l,r,x≤n,l≤r

    输出

    对于第三种操作输出答案即可,答案对109+7进行取模。

    样例输入

    5 8 
    1 2 3 4 5 
    1 2 4 
    3 2 
    3 3 
    2 2 5 
    3 2 
    3 5 
    1 5 5 
    3 5 
    

    样例输出

    4
    9
    2
    1
    1

    思路:线段树维护乘和除的次数;op==1时,乘的次数直接加1,op==2时,先抵消一个乘的次数,若乘全被抵消再给除的次数加1
    #include<bits/stdc++.h>
    #define mod 1000000007
    typedef long long ll;
    using namespace std;
    
    int n,m,a[100010];//区间长度
    struct Node{
      int l,r,sum,lazy;
    }node_mul[100010*4],node_div[100010*4];//节点数=区间长度*4
    
    void clearTree(Node node[]){
    for(int i=1;i<=n;i++) node[i].sum=0,node[i].lazy=0;
    }
    
    void build(Node node[],int k,int l,int r){
      node[k].l=l,node[k].r=r;
      if(l==r) return;
      else{
        int mid=(l+r)>>1;
        build(node,2*k,l,mid);
        build(node,2*k+1,mid+1,r);
      }
    }
    
    void pushdown(Node node[],int f,int k){
      if(f==0){
        node[2*k].sum+=node[k].lazy*(node[2*k].r-node[2*k].l+1);
        node[2*k].lazy+=node[k].lazy;
        node[2*k+1].sum+=node[k].lazy*(node[2*k+1].r-node[2*k+1].l+1);
        node[2*k+1].lazy+=node[k].lazy;
        node[k].sum-=node[k].sum*(node[k].r-node[k].l+1);
        node[k].lazy=0;
      }
      else{
        if(node_mul[2*k].lazy>=node[k].lazy){
            node_mul[2*k].sum-=node[k].lazy*(node_mul[2*k].r-node_mul[2*k].l+1);
            node_mul[2*k].lazy-=node[k].lazy;
        }
        else{
            node[2*k].sum+=(node[k].lazy-node_mul[2*k].lazy)*(node[2*k].r-node[2*k].l+1);
            node[2*k].lazy+=(node[k].lazy-node_mul[2*k].lazy);
            node_mul[2*k].sum-=node_mul[2*k].lazy*(node_mul[2*k].r-node_mul[2*k].l+1);
            node_mul[2*k].lazy=0;
        }
        if(node_mul[2*k+1].lazy>=node[k].lazy){
            node_mul[2*k+1].sum-=node[k].lazy*(node_mul[2*k+1].r-node_mul[2*k+1].l+1);
            node_mul[2*k+1].lazy-=node[k].lazy;
        }
        else{
            node[2*k+1].sum+=(node[k].lazy-node_mul[2*k+1].lazy)*(node[2*k+1].r-node[2*k+1].l+1);
            node[2*k+1].lazy+=(node[k].lazy-node_mul[2*k+1].lazy);
            node_mul[2*k+1].sum-=node_mul[2*k+1].lazy*(node_mul[2*k+1].r-node_mul[2*k+1].l+1);
            node_mul[2*k+1].lazy=0;
        }
        node[k].sum-=node[k].sum*(node[k].r-node[k].l+1);
        node[k].lazy=0;
      }
    }
    
    int ask_point_val(Node node[],int f,int k,int x){
      if(x<=0) return 0;
      if(node[k].l==node[k].r) return node[k].sum;
      else{
        //push_down时先除后乘
        if(node_div[k].lazy) pushdown(node_div,1,k);
        if(node_mul[k].lazy) pushdown(node_mul,0,k);
        int mid=(node[k].l+node[k].r)>>1;
        if(x<=mid) return ask_point_val(node,f,2*k,x);
        else return ask_point_val(node,f,2*k+1,x);
      }
    }
    
    void addval_to_interval(Node node[],int f,int k,int l,int r){
      if(l<=node[k].l&&node[k].r<=r){
        if(f==0){
            node[k].sum+=1*(node[k].r-node[k].l+1);
            node[k].lazy+=1;
        }
        else{
            if(node_mul[k].lazy){//若有乘,先抵消
                node_mul[k].sum-=1*(node[k].r-node[k].l+1);
                node_mul[k].lazy-=1;
            }
            else{//若无乘,直接加1
                node[k].sum+=1*(node[k].r-node[k].l+1);
                node[k].lazy+=1;
            }
        }
      }
      else{
        //push_down时先除后乘
        if(node_div[k].lazy) pushdown(node_div,1,k);
        if(node_mul[k].lazy) pushdown(node_mul,0,k);
        int mid=(node[k].l+node[k].r)/2;
        if(l<=mid) addval_to_interval(node,f,2*k,l,r);
        if(r>mid) addval_to_interval(node,f,2*k+1,l,r);
        node[k].sum=node[2*k].sum+node[2*k+1].sum;
      }
    }
    
    vector<int> factor[100010];
    void get_primefactor(int pos){
      int x=a[pos];
      if(x==1){
        factor[pos].push_back(1);
        return;
      }
      for(int i=2;i*i<=x;i++){
        if(x%i==0){
            while(x%i==0){
                factor[pos].push_back(i);
                x/=i;
            }
        }
      }
      if(x>1) factor[pos].push_back(x);
    }
    
    ll qpow(ll a,ll b){
      ll ret=1;
      while(b){
        if(b&1) ret=ret*a%mod;
        a=a*a%mod;
        b>>=1;
      }
      return ret;
    }
    
    int main()
    {
        clearTree(node_mul);clearTree(node_div);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            get_primefactor(i);
        }
        build(node_mul,1,1,n);build(node_div,1,1,n);
        for(int i=1;i<=m;i++){
            int op;scanf("%d",&op);
            if(op==1){
                int l,r;scanf("%d%d",&l,&r);
                addval_to_interval(node_mul,0,1,l,r);
            }
            else if(op==2){
                int l,r;scanf("%d%d",&l,&r);
                addval_to_interval(node_div,1,1,l,r);
            }
            else{
                int x;scanf("%d",&x);
                int num_mul=ask_point_val(node_mul,0,1,x);
                int num_div=ask_point_val(node_div,1,1,x);
                //printf("add=%d sub=%d
    ",num_mul,num_div);
                ll ans=1;
                int siz=factor[x].size();
                if(num_div<siz){
                  int tmp=factor[x][num_div];
                  for(int i=num_div;i<siz;i++) ans=ans*factor[x][i]%mod;
                  ans=ans*qpow(tmp,num_mul)%mod;
                }
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    linux 虚拟机web服务接入互联网
    golang操作数据库
    开启提示:press esc in 5 seconds to skip 如何操作
    如何将qcow2转为vhd
    统信UOS如何分卷压缩
    统信UOS欧拉版本如何制作启动盘
    UOS输错密码导致长时间锁定怎么办?
    在UOS中使用WPS编辑文件,忘记保存关闭了文件,怎么找回?
    uos server版一开始没有安装桌面,后面客户需要加装DDE桌面如何实现
    uos系统升级时,我不想升级相关软件包,应该如何去做
  • 原文地址:https://www.cnblogs.com/lllxq/p/10914009.html
Copyright © 2020-2023  润新知