zoukankan      html  css  js  c++  java
  • 【刷题】HDU 5869 Different GCD Subarray Query

    Problem Description

    This is a simple problem. The teacher gives Bob a list of problems about GCD (Greatest Common Divisor). After studying some of them, Bob thinks that GCD is so interesting. One day, he comes up with a new problem about GCD. Easy as it looks, Bob cannot figure it out himself. Now he turns to you for help, and here is the problem:

    Given an array (a) of (N) positive integers (a_1, a_2, cdots a_{N-1}, a_N) ; a subarray of (a) is defined as a continuous interval between (a_1) and (a_N) .In other words,(a_i, a_{i+1}, cdots, a_{j-1}, a_j) is a subarray of (a), for (1le ile jle N).For a query in the form ((L, R)) , tell the number of different GCDs contributed by all subarrays of the interval ([L, R]).

    Input

    There are several tests, process till the end of input.

    For each test, the first line consists of two integers (N) and (Q), denoting the length of the array and the number of queries, respectively. (N) positive integers are listed in the second line, followed by (Q) lines each containing two integers (L,R) for a query.

    You can assume that

    (1≤N,Q≤100000)

    (1≤a_i≤1000000)

    Output

    For each query, output the answer in one line.

    Sample Input

    5 3
    1 3 4 6 9
    3 5
    2 5
    1 5

    Sample Output

    6
    6
    6

    Description(CHN)

    给定一个数列,多次询问,每次询问 (L,R),求 ([L,R]) 中所有子区间的 (gcd) 有多少种

    Solution

    预处理对于数列中的每个位置,对于它为 (R) 的所有区间中不同的 (gcd) 出现的最右边的 (L) 是什么。这个东西直接在上一个位置的基础上枚举就好了
    将询问离线
    我们用BIT维护每种 (gcd) 出现的区间的 (L) 的最右的位置在哪里,然后就用差分计算答案就好了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=300000+10;
    int n,m,a[MAXN],ans[MAXN];
    std::map<int,int> M;
    std::vector< std::pair<int,int> > V[MAXN],query[MAXN];
    struct BIT{
    	int C[MAXN];
    	inline void init()
    	{
    		memset(C,0,sizeof(C));
    	}
    	inline int lowbit(int x)
    	{
    		return x&(-x);
    	}
    	inline void add(int x,int k)
    	{
    		while(x<=n)C[x]+=k,x+=lowbit(x);
    	}
    	inline int sum(int x)
    	{
    		if(!x)return 0ll;
    		int res=0;
    		while(x>0)res+=C[x],x-=lowbit(x);
    		return res;
    	}
    };
    BIT T;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    #define ft first
    #define sd second
    int main()
    {
    	while(scanf("%d%d
    ",&n,&m)!=EOF)
    	{
    		for(register int i=1;i<=n;++i)read(a[i]),V[i].clear(),query[i].clear();
    		T.init();M.clear();
    		V[1].push_back(std::make_pair(1,a[1]));
    		for(register int i=2;i<=n;++i)
    		{
    			int now=a[i];V[i].push_back(std::make_pair(i,a[i]));
    			for(register int j=0,lt=V[i-1].size();j<lt;++j)
    			{
    				std::pair<int,int> pr=V[i-1][j];
    				int d=std::__gcd(now,pr.sd);
    				if(d!=now)V[i].push_back(std::make_pair(pr.ft,d)),now=d;
    			}
    		}
    		for(register int i=1;i<=m;++i)
    		{
    			int l,r;read(l);read(r);
    			query[r].push_back(std::make_pair(i,l));
    		}
    		for(register int i=1;i<=n;++i)
    		{
    			for(register int j=0,lt=V[i].size();j<lt;++j)
    			{
    				std::pair<int,int> pr=V[i][j];
    				if(M[pr.sd])T.add(M[pr.sd],-1);
    				T.add(pr.ft,1);M[pr.sd]=pr.ft;
    			}
    			for(register int j=0,lt=query[i].size();j<lt;++j)
    			{
    				std::pair<int,int> pr=query[i][j];
    				ans[pr.ft]=T.sum(i)-T.sum(pr.sd-1);
    			}
    		}
    		for(register int i=1;i<=m;++i)printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Leetcode刷题记录--39. 组合总和
    Leetcode刷题记录--31. 下一个排列
    Leetcode刷题记录--22. 括号生成(回溯)
    Leetcode刷题记录--17. 电话号码的字母组合(回溯)
    分布式学习之--6.824MITLab1记录
    总结javascript处理异步的方法
    引用、浅拷贝及深拷贝 到 Map、Set(含对象assign、freeze方法、WeakMap、WeakSet及数组map、reduce等等方法)
    Vue之富文本tinymce爬坑录
    iOS 13 正式发布,来看看有哪些 API 变动
    Vuex,从入门到...
  • 原文地址:https://www.cnblogs.com/hongyj/p/9562843.html
Copyright © 2011-2022 走看看