[线段树]小花梨的数组
题目描述
小花梨得到了一个长度为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次操作,对于第三种操作输出结果。
⚫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
第二行输入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\n",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\n",ans); } } return 0; }
转载请注明出处:https://www.cnblogs.com/lllxq/