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;
    }
    
  • 相关阅读:
    JNI和NDK编程
    View的弹性滑动
    View的滑动
    《软件项目管理》课程
    《软件测试》课堂笔记05
    “MAVEN” 简单入门
    “Junit” 简单测试
    关于“百合测试”的实例
    关于“黑盒测试”的实例
    《软件测试》课堂笔记04
  • 原文地址:https://www.cnblogs.com/hongyj/p/9562843.html
Copyright © 2011-2022 走看看