您的位置:首页 > 其它

CodeForces 474F Ant colony 【线段树】【gcd】【二分】

2016-10-13 19:24 477 查看
题目:点击打开链接

题意:给定一个数列,求出区间长度减去询问区间内能被区间内所有其他的数整除的数出现的个数的值。

思路:将原数列存进一个结构体,先按照数列的值从小到大排序,相同时按照数列编号从小到大排序,因为a%b==0等价为gcd(a,b)==b,所以我们可以通过线段树或者ST表预处理出所有区间内的gcd值,然后查找到对应区间内的gcd值,就是该区间内能被区间内所有其他的数整除的数,然后通过二分结构体找到满足值相同的值的两端的位置,相减即为该数的个数,再用区间长度减去个数即可。

代码:

//线段树版本
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define PR pair<int,int>
#define MP make_pair
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define sqr(x) ((x)*(x))
#define ll long long
#define ull unsigned __int64
const ll INF = 1e18;
const int inf=0x3f3f3f3f;
const int M=15;
const int N=100100;
const int MOD=100000;
const double eps=1e-10;
const double pi=acos(-1.0);
using namespace std;

int n,m;
int a[N<<2];
PR b
;
int cnt;
int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}

void pushup(int rt)
{
a[rt]=gcd(a[rt<<1],a[rt<<1|1]);
}

void build(int l,int r,int rt)
{
if(l==r)
{
scanf("%d",&a[rt]);
b[++cnt].fi=a[rt];
b[cnt].se=cnt;
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 a[rt];
int m=(l+r)>>1;
int x=0,y=0;
if(L<=m) x=query(L,R,lson);
if(m<R) y=query(L,R,rson);
return gcd(x,y);
}

int main()
{
int i,j;
scanf("%d",&n);
build(1,n,1);
sort(b+1,b+1+n);
scanf("%d",&m);
for(i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
int tmp=query(l,r,1,n,1);
int mi=lower_bound(b+1,b+1+n,MP(tmp,l))-b;
int mx=lower_bound(b+1,b+1+n,MP(tmp,r+1))-b;
printf("%d\n",r-l+1-(mx-mi));
}
}

//ST版本
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define PR pair<int,int>
#define MP make_pair
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define sqr(x) ((x)*(x))
#define ll long long
#define ull unsigned __int64
const ll INF = 1e18;
const int inf=0x3f3f3f3f;
const int M=18;
const int N=100100;
const int MOD=100000;
const double eps=1e-10;
const double pi=acos(-1.0);
using namespace std;

int n,m;
int dp
[M],a
;
PR b
;

int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}

int main()
{
int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i].fi=dp[i][0]=a[i];
b[i].se=i;
}
sort(b+1,b+1+n);
for(j=1;j<18;j++)
for(i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
scanf("%d",&m);
for(i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
int k=log2(r-l+1);
int tmp=gcd(dp[l][k],dp[r-(1<<k)+1][k]);
int mi=lower_bound(b+1,b+1+n,MP(tmp,l))-b-1;
int mx=lower_bound(b+1,b+1+n,MP(tmp,r+1))-b-1;
printf("%d\n",r-l+1-(mx-mi));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: