码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ3585: mex

时间:2015-08-11 09:48:45      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:

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\n",ans[i]);
}
int main(){
    init();
    work();
    return 0;
}
my code

 

BZOJ3585: mex

标签:

原文地址:http://www.cnblogs.com/iamCYY/p/4719921.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!