zoukankan      html  css  js  c++  java
  • 【线段树】Gym

    题意:n个数,m次询问,每次给你一个询问v,l,r,问你v%a[l]%a[l+1]%...%a[r]是多少。

    a%b,结果要么不变,要么至少缩小到a的一半,于是用线段树,每次询问当前区间最靠左侧的小于等于当前数的值是多少,只需不超过log次询问就能使该数模完,就行了。

    O(n(logn)^2)。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int n,m;
    ll minv[800005],a[200005];
    void buildtree(int rt,int l,int r){
    	if(l==r){
    		scanf("%I64d",&minv[rt]);
    		a[l]=minv[rt];
    		return;
    	}
    	int m=(l+r>>1);
    	buildtree(rt<<1,l,m);
    	buildtree(rt<<1|1,m+1,r);
    	minv[rt]=min(minv[rt<<1],minv[rt<<1|1]);
    }
    int pos;
    int find(ll v,int rt,int l,int r){
    	if(l==r){
    		return l;
    	}
    	int m=(l+r>>1);
    	if(minv[rt<<1]<=v){
    		return find(v,rt<<1,l,m);
    	}
    	else{
    		return find(v,rt<<1|1,m+1,r);
    	}
    }
    bool query(int ql,int qr,ll v,int rt,int l,int r){
    	if(ql<=l && r<=qr){
    		if(minv[rt]<=v){
    			pos=find(v,rt,l,r);
    			return 1;
    		}
    		return 0;
    	}
    	int m=(l+r>>1);
    	if(ql<=m){
    		if(query(ql,qr,v,rt<<1,l,m)){
    			return 1;
    		}
    	}
    	if(m<qr){
    		if(query(ql,qr,v,rt<<1|1,m+1,r)){
    			return 1;
    		}
    	}
    	return 0;
    }
    int main(){
    //	freopen("j.in","r",stdin);
    	ll z;
    	int x,y;
    	scanf("%d%d",&n,&m);
    	buildtree(1,1,n);
    	for(int i=1;i<=m;++i){
    		scanf("%I64d%d%d",&z,&x,&y);
    		while(x<=y && query(x,y,z,1,1,n)){
    			z%=a[pos];
    			x=pos+1;
    		}
    		printf("%I64d
    ",z);
    	}
    	return 0;
    }
  • 相关阅读:
    20201022-1 每周例行报告
    2020高级软件工程“领跑衫”获奖感言
    20201015-3 每周例行报告
    20201008-1 每周例行报告
    竞拍作业
    20201207-总结-作业
    20201126-1每周例行报告
    20201120-1每周例行报告
    20201112 -1每周例行报告
    20201105-1例行报告
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7634873.html
Copyright © 2011-2022 走看看