D-query SPOJ - DQUERY

点击打开链接

和hdu3333基本一样 两种方法

主席树有时可看做是利用线段树做的一个前缀 但在这里并没有用到前缀和的性质 和线段树离线做法有些类似 都是把同一个数出现的位置尽量提前

#include <bits/stdc++.h>
using namespace std;

struct node
{
    int nl;
    int nr;
    int val;
};

node tree[1000010];
int num[30010],root[30010],mp[1000010];
int n,m,tot;

int build(int l,int r)
{
    int cur,m;
    cur=tot++;
    tree[cur].nl=0,tree[cur].nr=0,tree[cur].val=0;
    if(l==r) return cur;
    m=(l+r)/2;
    tree[cur].nl=build(l,m);
    tree[cur].nr=build(m+1,r);
    return cur;
}

int update(int rot,int tar,int val,int l,int r)
{
    int cur,m;
    cur=tot++;
    tree[cur]=tree[rot];
    tree[cur].val+=val;
    if(l==r) return cur;
    m=(l+r)/2;
    if(tar<=m) tree[cur].nl=update(tree[cur].nl,tar,val,l,m);
    else tree[cur].nr=update(tree[cur].nr,tar,val,m+1,r);
    return cur;
}

int query(int rot,int pl,int pr,int l,int r)
{
    int res,m;
    if(pl<=l&&r<=pr)
    {
        return tree[rot].val;
    }
    res=0,m=(l+r)/2;
    if(pl<=m) res+=query(tree[rot].nl,pl,pr,l,m);
    if(pr>m) res+=query(tree[rot].nr,pl,pr,m+1,r);
    return res;
}

int main()
{
    int i,q,l,r;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d",&num[i]);
        }
        memset(mp,0,sizeof(mp));
        tot=0;
        root[0]=build(1,n);
        for(i=1;i<=n;i++)
        {
            if(!mp[num[i]])
            {
                root[i]=update(root[i-1],i,1,1,n);
            }
            else
            {
                root[i]=update(root[i-1],mp[num[i]],-1,1,n);
                root[i]=update(root[i],i,1,1,n);
            }
            mp[num[i]]=i;
        }
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d%d",&l,&r);
            printf("%d\n",query(root[r],l,n,1,n));
        }
    }
    return 0;
}

 

还可以用线段树离线处理

#include <bits/stdc++.h>
using namespace std;

struct node1
{
    int l;
    int r;
    int val;
};

struct node2
{
    int l;
    int r;
    int id;
    int val;
};

map <int,int> mp;
node1 tree[120010];
node2 order[200010];
int ary[30010];
int n,q;

bool cmpI(node2 n1,node2 n2)
{
    return n1.r<n2.r;
}

bool cmpII(node2 n1,node2 n2)
{
    return n1.id<n2.id;
}

void pushup(int cur)
{
    tree[cur].val=tree[2*cur].val+tree[2*cur+1].val;
}

void build(int l,int r,int cur)
{
    int m;
    tree[cur].l=l;
    tree[cur].r=r;
    tree[cur].val=0;
    if(l==r) return;
    m=(l+r)/2;
    build(l,m,2*cur);
    build(m+1,r,2*cur+1);
}

void update(int tar,int val,int cur)
{
    if(tree[cur].l==tree[cur].r)
    {
        tree[cur].val=val;
        return;
    }
    if(tar<=tree[2*cur].r) update(tar,val,2*cur);
    else update(tar,val,2*cur+1);
    pushup(cur);
}

int query(int pl,int pr,int cur)
{
    int res;
    if(pl<=tree[cur].l&&tree[cur].r<=pr)
    {
        return tree[cur].val;
    }
    res=0;
    if(pl<=tree[2*cur].r) res+=query(pl,pr,2*cur);
    if(pr>=tree[2*cur+1].l) res+=query(pl,pr,2*cur+1);
    return res;
}

int main()
{
    int i,p;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d",&ary[i]);
        }
        scanf("%d",&q);
        for(i=1;i<=q;i++)
        {
            scanf("%d%d",&order[i].l,&order[i].r);
            order[i].id=i,order[i].val=0;
        }
        mp.clear();
        build(1,n,1);
        sort(order+1,order+q+1,cmpI);
        p=1;
        for(i=1;i<=q;i++)
        {
            while(p<=order[i].r)
            {
                if(mp[ary[p]]!=0) update(mp[ary[p]],0,1);
                update(p,1,1);
                mp[ary[p]]=p;
                p++;
            }
            order[i].val=query(order[i].l,order[i].r,1);
        }
        sort(order+1,order+q+1,cmpII);
        for(i=1;i<=q;i++)
        {
            printf("%d\n",order[i].val);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值