您的位置:首页 > 其它

BZOJ 3339/3585 Rmq Problem/mex 莫队算法

2016-03-13 15:29 513 查看
连线段树都不愿意打了。。明明线段树要短

至于区间转移

如果是新增一个数字,和当前维护的mex值比较,如果相等,即已经把最小缺失的数字补上了,因此暴力查找下一个数字。另外大于n的值不会影响答案,所以忽略即可。其实想想写个树状数组应该也可?带两个log伤不起。。

如果删除一个数字,而且比当前维护的mex值小,更新答案。

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 200005;
int block
, a
, c
, x
, t
;
struct Query { int l, r, i; } q
;
bool operator< (const Query &a, const Query &b) { return block[a.l] == block[b.l] ? a.r < b.r : a.l < b.l; }
int read() {
int s = 0, f = 1; char ch = getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s * f;
}
int now = 0;
void add(int x) {
if (x > n) return;
++t[x];
if (x == now || !x) while(t[now]) ++now;
}
void del(int x) {
if (x > n) return;
--t[x];
if (x < now && !t[x]) now = x;
}
void transform(int &l, int &r, int &ans, int ql, int qr) {
while (r < qr) add(c[++r]);
while (r > qr) del(c[r--]);
while (l < ql) del(c[l++]);
while (l > ql) add(c[--l]);
ans = now;
}

int main() {
int n, i, l = 1, r = 0, m, sz;
sz = (int) sqrt(n = read()); m = read();
for (i = 1; i <= n; ++i) c[i] = read(), block[i] = (i - 1) / sz + 1;
for (i = 1; i <= m; ++i) q[i].l = read(), q[i].r = read(), q[i].i = i;
sort(q + 1, q + m + 1);
for (i = 1; i <= m; ++i) transform(l, r, x[q[i].i], q[i].l, q[i].r);
for (i = 1; i <= m; ++i) printf("%u\n", x[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: