Codeforces Round #271 (Div. 2) F 线段树+pair

来源:互联网 发布:vm12虚拟机安装mac os 编辑:程序博客网 时间:2024/05/18 15:28



链接:戳这里


F. Ant colony
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard 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].

Examples
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.


题意:

给出n个数ai。T组询问l,r

对于每组询问[l,r] ,要求输出区间长度减去区间内能被所有区间内的数整除的个数(一个数能被整个区间整除)


思路:两个技巧,看了tourist真是好技巧

我的思路:线段树维护三个权值,一个区间gcd值,区间min值,区间min值出现的个数

然后对于每个询问,能被整个区间整除当然是区间最小值为区间的gcd值。减去最小值的个数就行了


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include <ctime>#include<queue>#include<set>#include<map>#include<stack>#include<iomanip>#include<cmath>#include<bitset>#define mst(ss,b) memset((ss),(b),sizeof(ss))///#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;#define INF (1ll<<60)-1#define Max 1e10using namespace std;int n;int a[100100];int mn[500100],g[500100],num[500100];int gcd(int a,int b){    return b==0?a:gcd(b,a%b);}void pushup(int root){    g[root]=gcd(g[root*2],g[root*2+1]);    if(mn[root*2]<mn[root*2+1]){        mn[root]=mn[root*2];        num[root]=num[root*2];    } else if(mn[root*2]>mn[root*2+1]){        mn[root]=mn[root*2+1];        num[root]=num[root*2+1];    } else if(mn[root*2]==mn[root*2+1]){        mn[root]=mn[root*2];        num[root]=num[root*2]+num[root*2+1];    }}void build(int root,int l,int r){    if(l==r){        num[root]=1;        mn[root]=a[l];        g[root]=a[l];        return ;    }    int mid=(l+r)/2;    build(root*2,l,mid);    build(root*2+1,mid+1,r);    pushup(root);}int query1(int root,int l,int r,int x,int y){    if(x<=l && y>=r){        return g[root];    }    int mid=(l+r)/2;    if(y<=mid) return query1(root*2,l,mid,x,y);    else if(x>mid) return query1(root*2+1,mid+1,r,x,y);    else {        return gcd(query1(root*2,l,mid,x,mid),query1(root*2+1,mid+1,r,mid+1,y));    }}int Num,Mn;void query3(int root,int l,int r,int x,int y){    if(x<=l && y>=r){        if(Mn>mn[root]){            Mn=mn[root];            Num=num[root];        } else if(Mn==mn[root]){            Num+=num[root];        }        return ;    }    int mid=(l+r)/2;    if(x<=mid) query3(root*2,l,mid,x,y);    if(y>mid) query3(root*2+1,mid+1,r,x,y);}int main(){    int T;    scanf("%d",&n);    for(int i=1;i<=n;i++) scanf("%d",&a[i]);    build(1,1,n);    scanf("%d",&T);    while(T--){        int l,r;        scanf("%d%d",&l,&r);        int Gcd=query1(1,1,n,l,r);        Num=0;Mn=Max;        query3(1,1,n,l,r);        ///printf("%d %d %d\n",Gcd,Mn,Num);        if(Gcd==Mn){            printf("%d\n",r-l+1-Num);        } else printf("%d\n",r-l+1);    }    return 0;}


接下来是tourist的:线段树维护区间的gcd值。

pair一个数组,当前第i个数对应的值为<ai,i>表示gcd值以及所在的位置编号。

然后排个序,这里的pair默认是先按第一个关键字排序。第一个关键字一样的话按第二个关键字排序

对于每组询问[l,r],已知区间的gcd值。

二分找出这个gcd值对应在pair里面的哪个位置,当pair里面的gcd出现多个的时候,找出第一个>=当前询问的l和r+1

分别为x和y

然后贡献就是r-l+1-(y-x)


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include <ctime>#include<queue>#include<set>#include<map>#include<stack>#include<iomanip>#include<cmath>#include<bitset>#define mst(ss,b) memset((ss),(b),sizeof(ss))///#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;#define INF (1ll<<60)-1#define Max 1e10using namespace std;int n;int a[100100];int g[500100];int gcd(int a,int b){    return b==0?a:gcd(b,a%b);}void pushup(int root){    g[root]=gcd(g[root*2],g[root*2+1]);}void build(int root,int l,int r){    if(l==r){        g[root]=a[l];        return ;    }    int mid=(l+r)/2;    build(root*2,l,mid);    build(root*2+1,mid+1,r);    pushup(root);}int query1(int root,int l,int r,int x,int y){    if(x<=l && y>=r){        return g[root];    }    int mid=(l+r)/2;    if(y<=mid) return query1(root*2,l,mid,x,y);    else if(x>mid) return query1(root*2+1,mid+1,r,x,y);    else {        return gcd(query1(root*2,l,mid,x,mid),query1(root*2+1,mid+1,r,mid+1,y));    }}pair<int,int> p[100100];int main(){    int T;    scanf("%d",&n);    for(int i=1;i<=n;i++) {        scanf("%d",&a[i]);        p[i]=make_pair(a[i],i);    }    sort(p+1,p+n+1);    build(1,1,n);    scanf("%d",&T);    while(T--){        int l,r;        scanf("%d%d",&l,&r);        int Gcd=query1(1,1,n,l,r);        int x=lower_bound(p+1,p+n+1,make_pair(Gcd,l))-p;        int y=lower_bound(p+1,p+n+1,make_pair(Gcd,r+1))-p;        printf("%d\n",r-l+1-(y-x));    }    return 0;}


0 0
原创粉丝点击