codeforces 474F 区间gcd + 离散化

F. Ant colony
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Mole is hungry again. He found one ant colony, consisting of n ants, ordered in a row. Each ant i (1 ≤ i ≤ n) has a strength si.

In order to make his dinner more interesting, Mole organizes a version of «Hunger Games» for the ants. He chooses two numbers l and r (1 ≤ l ≤ r ≤ n) and each pair of ants with indices between l and r (inclusively) will fight. When two ants i and j fight, ant i gets one battle point only if si divides sj (also, ant j gets one battle point only if sj divides si).

After all fights have been finished, Mole makes the ranking. An ant i, with vi battle points obtained, is going to be freed only if vi = r - l, or in other words only if it took a point in every fight it participated. After that, Mole eats the rest of the ants. Note that there can be many ants freed or even none.

In order to choose the best sequence, Mole gives you t segments [li, ri] and asks for each of them how many ants is he going to eat if those ants fight.

Input

The first line contains one integer n (1 ≤ n ≤ 105), the size of the ant colony.

The second line contains n integers s1, s2, ..., sn (1 ≤ si ≤ 109), the strengths of the ants.

The third line contains one integer t (1 ≤ t ≤ 105), the number of test cases.

Each of the next t lines contains two integers li and ri (1 ≤ li ≤ ri ≤ n), describing one query.

Output

Print to the standard output t lines. The i-th line contains number of ants that Mole eats from the segment [li, ri].

Sample test(s)
Input
5
1 3 2 4 2
4
1 5
2 5
3 5
4 5
Output
4
4
1
1
Note

In the first test battle points for each ant are v = [4, 0, 2, 0, 2], so ant number 1 is freed. Mole eats the ants 2, 3, 4, 5.

In the second test case battle points are v = [0, 2, 0, 2], so no ant is freed and all of them are eaten by Mole.

In the third test case battle points are v = [2, 0, 2], so ants number 3 and 5 are freed. Mole eats only the ant 4.

In the fourth test case battle points are v = [0, 1], so ant number 5 is freed. Mole eats the ant 4.


就是简单的用线段数求一下区间gcd,然后统计一下区间内这个gcd的个数。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <functional>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctime>
typedef long long ll;
//typedef pair<int,int> pii;
#define INF 1e9
#define MAXN 100005
#define MAXM 100
const int maxn = 100005;
const int mod = 1000000007 ;
#define eps 1e-6
#define PI 3.1415926535897932384626433
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define scan(n) scanf("%d",&n)
#define scan2(n,m) scanf("%d%d",&n,&m)
#define scans(s) scanf("%s",s);
#define ini(a) memset(a,0,sizeof(a))
#define FILL(a,n) fill(a,a+maxn,n)
#define out(n) printf("%d\n",n)
ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b);}
#define mk(n,m) make_pair(n,m)
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
vector<int> G[100005];
map<int,int> mp;
int g[maxn<<2];
int cnt = 0;
int insert(int n)
{
	if(mp.find(n) == mp.end())
		mp[n] = cnt++;
	return mp[n];
}
void pushup(int rt)
{
	g[rt] = gcd(g[rt<<1],g[rt<<1|1]);
}
void build(int l,int r,int rt)
{
	if(l == r)
	{
		scanf("%d",&g[rt]);
		int aa = insert(g[rt]);
		G[aa].push_back(l);
		return;
	}
	int m = (l+r) >> 1;
	build(lson);
	build(rson);
	pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
	if (L <= l && r <= R)
	{
		return g[rt];
	}

	int m = (l+r)>>1;
	int t1 = -1,t2 = -1;
	if(L <= m) t1 = query(L,R,lson);
	if(R > m) t2 = query(L,R,rson);
	if(t1 != -1 && t2 != -1) return gcd(t1,t2);
	else if(t1 != -1) return t1;
	else if(t2 != -1) return t2;
	return 1;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
	//   freopen("out.txt","w",stdout);
#endif
	int n;
	while(~scanf("%d",&n))
	{
		rep(i,maxn) G[i].clear();
		mp.clear();
		cnt = 0;
		build(1,n,1);
		int m;
		cin>>m;
		int L,R;
		while(m--)
		{
			scanf("%d%d",&L,&R);
			int gg = query(L,R,1,n,1);
			if(mp.find(gg) == mp.end())
			{
				printf("%d\n",R-L+1);
				continue;
			}
			gg = mp[gg];
			int p1 = lower_bound(G[gg].begin(),G[gg].end(),L) - G[gg].begin();
			int p2 = upper_bound(G[gg].begin(),G[gg].end(),R) - G[gg].begin();
			int ans = R-L+1 - (p2-p1);
			printf("%d\n",ans);
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
区间DP是一种动态规划的方法,用于解决区间范围内的问题。在Codeforces竞赛中,区间DP经常被用于解决一些复杂的字符串或序列相关的问题。 在区间DP中,dp[i][j]表示第一个序列前i个元素和第二个序列前j个元素的最优解。具体的转移方程会根据具体的问题而变化,但是通常会涉及到比较两个序列的元素是否相等,然后根据不同的情况进行状态转移。 对于区间长度为1的情况,可以先进行初始化,然后再通过枚举区间长度和区间左端点,计算出dp[i][j]的值。 以下是一个示例代码,展示了如何使用区间DP来解决一个字符串匹配的问题: #include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> using namespace std; const int maxn=510; const int inf=0x3f3f3f3f; int n,dp[maxn][maxn]; char s[maxn]; int main() { scanf("%d", &n); scanf("%s", s + 1); for(int i = 1; i <= n; i++) dp[i][i] = 1; for(int i = 1; i <= n; i++) { if(s[i] == s[i - 1]) dp[i][i - 1] = 1; else dp[i][i - 1] = 2; } for(int len = 3; len <= n; len++) { int r; for(int l = 1; l + len - 1 <= n; l++) { r = l + len - 1; dp[l][r] = inf; if(s[l] == s[r]) dp[l][r] = min(dp[l + 1][r], dp[l][r - 1]); else { for(int k = l; k <= r; k++) { dp[l][r] = min(dp[l][r], dp[l][k] + dp[k + 1][r]); } } } } printf("%d\n", dp[n]); return 0; } 希望这个例子能帮助你理解区间DP的基本思想和应用方法。如果你还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值