您的位置:首页 > 其它

BZOJ 2120 带修改莫队

2017-10-31 11:34 204 查看
简略题意:单点修改,区间查询不同颜色个数。

带修改莫队的板题,学习了一个。

和普通莫队的区别在于块的大小需要设定为n2/3,这样可以确保复杂度为O(n3/5)。

每次询问之前需要把在当前时间点之前的所有修改用上,这之后的所有修改删掉。

#define others
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
const double eps = 1e-8;
int dcmp(double x) { if(fabs(x)<=eps) return 0; return (x>0)?1:-1;};
typedef long long LL;
typedef unsigned long long ULL;

void file() {
freopen("out.txt", "r", stdin);
freopen("out1.txt", "w", stdout);
}

namespace Solver {
const int maxn = 11000;
int val[maxn], ans[maxn];
int col[1100000];
int res;
int n, m, q;
int sz;
int L = 1, R = 0, T = 0;

struct Mo {
int l, r, t, id;
bool operator < (const Mo & b) const {
if(l/sz != b.l/sz) return l/sz < b.l/sz;
if(r/sz != b.r/sz) return r/sz < b.r/sz;
return t < b.t;
}
} ask[maxn];
bool cmp(Mo a, Mo b) {
return a.id < b.id;
}
struct Mo_sub {
int x, y, z;
} upd[maxn];

void del(int x) {
col[val[x]]--;
if(col[val[x]] == 0) res--;
}
void ins(int x) {
if(col[val[x]] == 0) res++;
col[val[x]] ++;
}
void time_ins(int t) {
int x = upd[t].x, y = upd[t].y, &pre = upd[t].z;
if(x >= L && x <= R) del(x);
pre = val[x];
val[x] = y;
if(x >= L && x <= R) ins(x);
}
void time_del(int t) {
int x = upd[t].x, y = upd[t].y, pre = upd[t].z;
if(x >= L && x <= R) del(x);
val[x] = pre;
if(x >= L && x <= R) ins(x);
}
void solve() {
scanf("%d%d", &n, &m);
sz = powf(n, 2.0/3);
for(int i = 1; i <= n; i++) scanf("%d", &val[i]);
int cnt1, cnt2; cnt1 = cnt2 = 0;
for(int i = 1; i <= m; i++) {
char ch; int x, y;
scanf(" %c%d%d", &ch, &x, &y);
if(ch == 'Q')
cnt1++, ask[cnt1] = {x, y, cnt2, i};
else
cnt2++, upd[cnt2] = {x, y, 0};
}
sort(ask+1, ask+1+cnt1);
for(int i = 1; i <= cnt1; i++) {
while(L < ask[i].l) del(L), L++;
while(R < ask[i].r) R++, ins(R);
while(L > ask[i].l) L--, ins(L);
while(R > ask[i].r) del(R), R--;
while(T > ask[i].t) time_del(T), T--;
while(T < ask[i].t) T++, time_ins(T);
ans[ask[i].id] = res;
}
sort(ask+1, ask+1+cnt1, cmp);
for(int i = 1; i <= cnt1; i++) printf("%d\n", ans[ask[i].id]);
}
}

int main() {
Solver::solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: