• BZOJ3585: mex


    http://www.lydsy.com/JudgeOnline/problem.php?id=3585

      对于每次查询的区间[l,r],将权值分块,维护每一块内数字的出现次数,和每个权值的出现次数。因为mex值不会超过区间长度,这样我们就可以在O(√n)的时间内得到一个没有全被覆盖的区间,然后再O(√n)的时间暴力枚举当前块内的每个数,看是否出现过,即可得到答案。我们发现统计的信息可以在O(1)的时间内转移,于是用莫队算法来支持多次询问。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=200015,maxb=515;
    int n,m,siz,a[maxn];
    struct Tquery{int idx,l,r;}Q[maxn];
    bool cmp(Tquery x,Tquery y){
        if (x.l/siz!=y.l/siz) return x.l/siz<y.l/siz;
        else return x.r<y.r;
    }
    void init(){
        scanf("%d%d",&n,&m);siz=sqrt(n);
        for (int i=1;i<=n;++i) scanf("%d",&a[i]);
        for (int l,r,i=1;i<=m;++i){scanf("%d%d",&l,&r);Q[i]=(Tquery){i,l,r};}
        sort(Q+1,Q+m+1,cmp);
    }
    int ans[maxn],sum[maxn],have[maxb];
    void solve(int k){
        for (int i=Q[k-1].l;i<=Q[k].l-1;++i) if (a[i]<=n) if (!--sum[a[i]]) --have[a[i]/siz];
        for (int i=Q[k-1].l-1;i>=Q[k].l;--i) if (a[i]<=n) if (!sum[a[i]]++) ++have[a[i]/siz];
        for (int i=Q[k-1].r;i>=Q[k].r+1;--i) if (a[i]<=n) if (!--sum[a[i]]) --have[a[i]/siz];
        for (int i=Q[k-1].r+1;i<=Q[k].r;++i) if (a[i]<=n) if (!sum[a[i]]++) ++have[a[i]/siz];
        int pos;for (pos=0;have[pos]==siz;++pos);
        for (ans[Q[k].idx]=pos*siz;sum[ans[Q[k].idx]];++ans[Q[k].idx]);
    }
    void work(){
        Q[0]=(Tquery){0,1,0};for (int i=1;i<=m;++i) solve(i);
        for (int i=1;i<=m;++i) printf("%d
    ",ans[i]);
    }
    int main(){
        init();
        work();
        return 0;
    }
    my code
  • 相关阅读:
    java读取excel文件内容
    JavaScript函数写法整理
    Redis命令
    Redis简单入门
    Redis介绍
    NodeJS代码调试
    React组件生命周期
    解决swiper动态改变数据后分页混乱问题
    [LeetCode] 343. Integer Break
    [LeetCode] 304. Range Sum Query 2D
  • 原文地址:https://www.cnblogs.com/iamCYY/p/4719921.html
Copyright © 2020-2023  润新知