题解 | #薯片

深蓝刃麟龙人

https://ac.nowcoder.com/acm/contest/53642/A

薯片

使用了树状数组。用一个数组维护对应值的已知的最大右边界。对查询先离线处理,将其右边界从小到大排序。遍历每个查询时先更新到对应的右边界,更新碰到之前出现过的值,把之前的标记取消,更新当前位置的新标记。更新完后就可以用树状数组求和来求区间

#include <bits/stdc++.h>
typedef long long ll;
const ll maxn=1e6+5;
using namespace std;

ll a[maxn];
ll pre[maxn];
ll ans[maxn];
ll tree[maxn];
ll n;ll m;

struct Query{
    ll l,r;
    ll id;
    bool operator < (const Query &x) const{
        return r<x.r;
    }
    
}q[maxn];

ll lowbit(ll x)
{
    return x&(-x);
}

void Update(ll x,ll val)
{
    for(;x<=n;x+=lowbit(x))
        tree[x]+=val;
}

ll cal(ll x)
{
    ll sum=0;
    for(;x>0;x-=lowbit(x))
        sum+=tree[x];
    return sum;
}



int main(){
    
    ll i,j;
    
    scanf("%lld",&n);
    
    for(i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    
    scanf("%lld",&m);
    
    for(i=1;i<=m;i++)
    {
        scanf("%lld%lld",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    sort(q+1,q+m+1);
    
    ll p=1;
    
    for(i=1;i<=m;i++)
    {
        for(;p<=q[i].r;p++)
        {
            if(pre[a[p]])
                Update(pre[a[p]],-1);
            Update(p,1);
            pre[a[p]]=p;
        }
        ans[q[i].id]=cal(q[i].r)-cal(q[i].l-1);
    }
    
    for(i=1;i<=m;i++)
        printf("%lld\n",ans[i]);
    
}
全部评论

相关推荐

06-02 15:53
阳光学院 Java
点赞 评论 收藏
分享
06-12 16:50
已编辑
小米_软件开发(准入职员工)
晓沐咕咕咕:评论区没被女朋友好好对待过的计小将可真多。觉得可惜可以理解,毕竟一线大厂sp。但是骂楼主糊涂的大可不必,说什么会被社会毒打更是丢人。女朋友体制内生活有保障,读研女朋友还供着,都准备订婚了人家两情相悦,二线本地以后两口子日子美滋滋,哪轮到你一个一线城市房子都买不起的996清高计小将在这说人家傻😅
点赞 评论 收藏
分享
06-18 16:45
门头沟学院 Java
玩脱了,吊着两家结果两家都不要鼠鼠了,我真想给自己两巴掌。
凉风落木楚山秋:当作是你把这两家公司从地球开除了就行了
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务