zoukankan      html  css  js  c++  java
  • SPOJ

    题目链接:https://vjudge.net/problem/SPOJ-DQUERY

    题目大意:给定一个含有n个数的序列,有q个询问,每次询问区间[l,r]中不同数的个数。

    解题思路:从左向右一个一个将该数字处在的位置添加到主席树中

    如果该数字前面未出现过,则在此版本的线段树中的该条链加1,如果该数字已经出现过了,则在此版本线段树的上次出现位置减1,再在此版本线段树的该位置加1,这样就能保证区间不重复计算。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=30005;
    struct node{
        int l,r,sum;
    }T[maxn*40];
    int n,q,a[maxn],cnt,root[maxn],pos[1000005];
    void update(int &now,int pre,int val,int l,int r,int pos){
        T[++cnt]=T[pre],T[cnt].sum+=val,now=cnt;
        if(l==r) return;
        int mid=l+r>>1;
        if(pos<=mid) update(T[now].l,T[pre].l,val,l,mid,pos);
        else update(T[now].r,T[pre].r,val,mid+1,r,pos);
    }
    int query(int L,int R,int l,int r,int rt){
        if(L<=l&&R>=r) return T[rt].sum;
        int ans=0,mid=l+r>>1;
        if(L<=mid) ans+=query(L,R,l,mid,T[rt].l);
        if(R>mid) ans+=query(L,R,mid+1,r,T[rt].r);
        return ans;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++){
            if(pos[a[i]]){
                update(root[i],root[i-1],-1,1,n,pos[a[i]]);
                update(root[i],root[i],1,1,n,i);
            }else update(root[i],root[i-1],1,1,n,i);
            pos[a[i]]=i;
        } 
        scanf("%d",&q);
        while(q--){
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d
    ",query(l,r,1,n,root[r]));
        }
        return 0;
    }
  • 相关阅读:
    jmeter jsr223脚本引用变量的问题
    apk反编译
    JS时间对像
    无缝滚动
    带详情图片轮播
    飘动文字2
    飘动的文字1
    抖动图片2
    点击图片图片上下抖动
    点击div掉下和上升
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/11257876.html
Copyright © 2011-2022 走看看