zoukankan      html  css  js  c++  java
  • “美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学) E 小花梨的数组 线段树

    题意

    分析

    预处理出每个数的最小素因子,首先可以知道(minprime(x*minprime(x))=minprime(x)),我们用线段树维护区间最大值(mx[p]),注意这里的最大值并不是实际的最大值,同时维护区间(a[i])(minprime(a[i]))的次数的最小值(mnt[p])

    • 对于操作1,直接区间更新(mnt[p])加1。

    • 对于操作2,有两种情况:

      • (mnt[p]=0)时,表示当前区间内至少有一个数乘最小素因子的次数为0,一个数除以它的最小素因子后它的最小素因子可能会变化,当一个数为1时,无论怎么操作它都不会再变了,而一个数除它的最小素因子最多(log)次就会变成1,所以此时我们直接暴力更新(mx[p]=mx[p]/minprime(mx[p]));

      • (mnt[p] ot= 0时),直接区间更新(mnt[p])减1。

    • 对于操作3,单点查询(mx[p])(mnt[p]),答案为(mx[p] imes minprime(mx[p])^{mnt[p]}),用快速幂算一下就行了。

    为什么维护区间最大值(mx[p])呢,因为当(mx[p]=1)时可以直接剪枝。

    时间复杂度(O(n*log(max(a[i]))*log(n)))

    Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    #define ll long long
    using namespace std;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=1e5+10;
    typedef pair<int,int> pii;
    int n,m;
    int a[maxn];
    int mp[10*maxn];
    int mx[maxn<<2],mnt[maxn<<2],tag[maxn<<2];
    void pp(int p){
    	mx[p]=max(mx[p<<1],mx[p<<1|1]);
    	mnt[p]=min(mnt[p<<1],mnt[p<<1|1]);
    }
    void pd(int p,int k){
    	mnt[p]+=k;
    	tag[p]+=k;
    }
    void bd(int l,int r,int p){
    	if(l==r){
    		mx[p]=a[l];
    		return;
    	}int mid=l+r>>1;
    	bd(lson);bd(rson);pp(p);
    }
    void up(int dl,int dr,int l,int r,int p,int k){
    	if(mx[p]==1) return;
    	if(l>=dl&&r<=dr){
    		if(mnt[p]==0&&k==-1){
    			if(l==r){
    				mx[p]/=mp[mx[p]];
    				return;
    			}
    		}else{
    			mnt[p]+=k;
    			tag[p]+=k;
    			return;
    		}
    	}int mid=l+r>>1;
    	pd(p<<1,tag[p]);pd(p<<1|1,tag[p]);tag[p]=0;
    	if(dl<=mid) up(dl,dr,lson,k);
    	if(dr>mid) up(dl,dr,rson,k);
    	pp(p);
    }
    pii qy(int x,int l,int r,int p){
    	if(l==r){
    		return pii(mx[p],mnt[p]);
    	}int mid=l+r>>1;
    	pd(p<<1,tag[p]);pd(p<<1|1,tag[p]);tag[p]=0;
    	if(x<=mid) return qy(x,lson);
    	else return qy(x,rson);
    }
    int getmp(int x){
    	for(int i=2;i*i<=x;i++){
    		if(x%i==0) return i;
    	}
    	return x;
    }
    ll ksm(ll a,ll b){
    	ll ret=1;
    	while(b){
    		if(b&1) ret=ret*a%mod;
    		b>>=1;
    		a=a*a%mod;
    	}
    	return ret;
    }
    int main(){
    	//ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    	}mp[1]=1;
    	for(int i=2;i<=1000000;i++){
    		mp[i]=getmp(i);
    	}bd(1,n,1);
    	while(m--){
    		int op,l,r,x;
    		scanf("%d",&op);
    		if(op==1){
    			scanf("%d%d",&l,&r);
    			up(l,r,1,n,1,1);
    		}else if(op==2){
    			scanf("%d%d",&l,&r);
    			up(l,r,1,n,1,-1);
    		}else{
    			scanf("%d",&x);
    			pii ret=qy(x,1,n,1);
    			ll ans=1ll*ret.fi*ksm(mp[ret.fi],ret.se)%mod;
    			printf("%lld
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    hibernate连接MySQL配置hibernate.cfg.xml
    行百里者半九十 —— 查找算法
    行百里者半九十 —— 链表(1)
    行百里者半九十 —— 查找算法(中等)
    行百里者半九十 —— 字符串
    设计模式 —— 总结
    并发编程 —— 使用条件变量构建线程安全队列
    行百里者半九十 ——栈与队列
    设计模式 —— 命令模式
    css选择器中:firstchild与:firstoftype的区别
  • 原文地址:https://www.cnblogs.com/xyq0220/p/11466069.html
Copyright © 2011-2022 走看看