您的位置:首页 > 其它

线段叔叔

2014-09-18 13:14 176 查看
原先好像就见过这样的题,然后那时候不会做,就是因为出现需要连续取数这样的情况,,,然后当时都懒得想。。。。还是队友机智。。。

嗯,稍稍存下即可,因为是区间询问。

(不一样的线段树~)读入优化~~~~~有个地方一直弄了好久 ,就是n==1的时候要特判,不然树都建不出来。。。

说下这样连续取数的情况,只要建树的时候每个数都和左边的数做一次gcd,到后面就是一样的线段树了,之前预处理一下就可以了。

#include <stdio.h>
#define maxn 100010
int tree[maxn*5];
int vis[110];
int a[maxn];
int top;
int gcd(int a,int b)
{
    int c=a%b;
    while(c)
    {
        a=b;
        b=c;
        c=a%b;
    }
    return b;
}
template<class T>
inline char read(T &n){
    T x = 0, tmp = 1; char c = getchar();
    while((c < '0' | c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return c;
}
template <class T>
inline void write(T n) {
    if(n < 0) {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n) {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
void creat(int l,int r,int rt)
{
    if(l==r)
    {
        tree[rt]=gcd(a[top-1],a[top]);
    //    printf("tree=%d  %d\n",tree[rt],rt);
        top++;
        vis[tree[rt]]=1;
        return;
    }
    int mid=(l+r)/2;
    creat(l,mid,rt<<1);
    creat(mid+1,r,rt<<1|1);
    tree[rt]=gcd(tree[rt<<1],tree[rt<<1|1]);
    vis[tree[rt]]=1;
    return;
}
void init()
{
    for(int i=1;i<=100;i++) vis[i]=0;
}
int main()
{
    int n;
    while(1)
    {
        read(n);
        if(n==0) break;
        init();
        int i,j,k;
        top=2;
        for(i=1;i<=n;i++)
        {
                //scanf("%d",&a[i]);
                read(a[i]);
                vis[a[i]]=1;
        }
        if(n==1) {printf("1\n");continue;}
        creat(1,n-1,1);
        int sum=0;
        for(i=1;i<=100;i++) if(vis[i]) sum++;
        printf("%d\n",sum);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: