• bzoj 2742(树状数组)


    传送门

    题意:

    给你一个长度为n的数列,其中有c种颜色,有q个询问,每个询问问你在区间[l,r]中,有多少种颜色的个数大于2。

    分析:

    这个题目跟求区间内不同的数的个数的解法非常相似。我们在这题中同样采取离线树状数组的做法。

    我们发现,倘若处于位置(l)的第(i)种颜色(c_i)要贡献答案,那么在位置(l)之后某个位置(r)必须要存在一个同样种类的颜色,那么在区间([l,r])中颜色(c_i)就能贡献答案。那么我们不妨记录一个数组(nex[i]),代表当前处于位置(i)的颜色(c_i)的下一个出现的位置。我们发现之后的结点能否对答案进行贡献,取决于当前位置,因此我们考虑从左到右更新树状数组。

    我们将询问的区间按照左端点排序,并从左到右进行遍历,倘若遍历到位置(i),在之后还存在颜色(c_i),即(nex[i])存在,那么我们需要删除(nex[i])的贡献;同时如果(nex[nex[i]])存在,即证明在区间([~nex[i]~,~nex[nex[i]]~])中,(c_i)能够贡献答案,故我们需要增加(nex[nex[i]])的贡献。

    每次更新完之后我们只需要在树状数组中查询询问区间的个数即可。

    代码:

    // luogu-judger-enable-o2
    #include <bits/stdc++.h>
    #define maxn 2000005
    using namespace std;
    struct Node{
        int l,r,pos;
        bool operator <(const Node &b)const{
            if(l==b.l) return r<b.r;
            else return l<b.l;
        }
    }q[maxn];
    int bit[maxn*2],a[maxn],mp[maxn],nex[maxn],ans[maxn];
    int lowbit(int x){
        return x&-x;
    }
    void update(int pos,int val){
        for(int i=pos;i<maxn;i+=lowbit(i)){
            bit[i]+=val;
        }
    }
    int query(int pos){
        int res=0;
        for(int i=pos;i>0;i-=lowbit(i)){
            res+=bit[i];
        }
        return res;
    }
    int main()
    {
        int n,c,m;
        scanf("%d%d%d",&n,&c,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=n;i>=1;i--) {
            nex[i] = mp[a[i]];
            mp[a[i]] = i;
        }
        for(int i=1;i<=c;i++){
            if(mp[i]&&nex[mp[i]]){
                update(nex[mp[i]],1);
            }
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].pos=i;
        }
        sort(q+1,q+1+m);
        int pre=1;
        for(int i=1;i<=m;i++){
            for(;pre<q[i].l;pre++){
                if(nex[pre]) update(nex[pre],-1);
                if(nex[pre]&&nex[nex[pre]]) update(nex[nex[pre]],1);
            }
            ans[q[i].pos]=query(q[i].r)-query(q[i].l-1);
        }
    
        for(int i=1;i<=m;i++){
            printf("%d
    ",ans[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    Mac下持续集成-查看占用的端口及kill
    windons模拟linux终端工具----cmder
    windows中使用django时报错:A server error occurred. Please contact the administrator.
    Pycharm和Navicat免费全功能版资源(即破解版)
    git常用命令
    pycharm常用的快捷键
    CSS3的媒体查询
    CSS列表中与list-style=none等价的样式
    CSS3中的mouse事件(mouseleave,mouseenter,mouseout,mouseover)
    CSS层级(浮动,定位的层级提升)
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11345962.html
Copyright © 2020-2023  润新知