day-15
莫队
普通莫队
注意顺序正确!!
codes
for (int i = 1; i <= m; i++) {
int pl = q[i].l, pr = q[i].r;
while (l > pl) add(a[--l]);
while (r < pr) add(a[++r]);
while (l < pl) del(a[l++]);
while (r > pr) del(a[r--]);
ans[q[i].id] = cal(q[i].R) - cal(q[i].L - 1);
}
值域二分
https://acm.hdu.edu.cn/showproblem.php?pid=6959
\(O(1)\)修改,\(O(sqrt(m))\)查询,在n,m等阶的情况下 ,复杂度平均只有\(O(n*sqrt(n)+ m*sqrt(n))\)比线段树等数据结构维护O(long(n))地修改查询优.
upd: 多组输入注意memset..
codes
const int maxn = 1e5 + 7;
int n, m, t, k = sqrt(maxn), a[maxn], num[maxn], sum[maxn], ans[maxn];
struct query {
int l, r, L, R, id;
} q[maxn];
bool cmp(query a, query b) {
if (a.l / k != b.l / k)
return a.l / k < b.l / k;
if ((a.l / k) & 1)
return a.r < b.r;
else
return a.r > b.r;
}
void add(int x) {
num[x]++;
if (num[x] == 1)
sum[x / k]++;
}
void del(int x) {
num[x]--;
if (num[x] == 0)
sum[x / k]--;
}
int cal(int x) {
int res = 0;
for (int i = 0; i < x / k; i++)
res += sum[i];
for (int i = (x / k) * k; i <= x; i++)
res += (num[i] >= 1);
return res;
}
void solve() {
cin >> t;
while (t--) {
memset(num, 0, sizeof num);
memset(sum, 0, sizeof sum);
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= m; i++)
cin >> q[i].l >> q[i].L >> q[i].r >> q[i].R, q[i].id = i;
sort(q + 1, q + 1 + m, cmp);
int l = 1, r = 0;
for (int i = 1; i <= m; i++) {
int pl = q[i].l, pr = q[i].r;
while (l > pl) add(a[--l]);
while (r < pr) add(a[++r]);
while (l < pl) del(a[l++]);
while (r > pr) del(a[r--]);
ans[q[i].id] = cal(q[i].R) - cal(q[i].L - 1);
}
for (int i = 1; i <= m; i++)
cout << ans[i] << "\n";
}
}
带修莫队
-
修改记录时间,修改值,修改后值 同时读入修改时进行修改,修改结束后还原
-
分块大小:\(pow(n,2.0/3)\)
codes
const int maxn = 2e6 + 7;
int n, t, qn, m, k, a[maxn], ans[maxn], num[maxn], sum;
char op;
struct query {
int l, r, t, id;
} q[maxn];
struct change {
int pl, val, oval;
} chg[maxn];
bool cmp(query a, query b) {
if (a.l / k != b.l / k) return a.l / k < b.l / k;
if (a.r / k != b.r / k) return a.r / k < b.r / k;
return a.t < b.t;
}
void add(int x) {
if (x == 0)
return;
num[x]++;
sum += (num[x] == 1);
}
void del(int x) {
if (x == 0)
return;
num[x]--;
sum -= (num[x] == 0);
}
int l = 1, r = 0, tn = 0;
void addchange(int t) {
int pl = chg[t].pl, val = chg[t].val;
if (pl >= l && pl <= r)
add(val), del(a[pl]);
a[pl] = val;
}
void delchange(int t) {
int pl = chg[t].pl, val = chg[t].oval;
if (pl >= l && pl <= r)
add(val), del(a[pl]);
a[pl] = val;
}
void solve() {
cin >> n >> m;
k = pow(n, 2.0 / 3);
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1, l, r; i <= m; i++) {
cin >> op >> l >> r;
if (op == 'R') chg[++t].pl = l, chg[t].val = r, chg[t].oval = a[l], a[l] = r;
else q[++qn].l = l, q[qn].r = r, q[qn].t = t, q[qn].id = qn;
}
for (int i = t; i >= 1; i--) a[chg[i].pl] = chg[i].oval;
sort(q + 1, q + 1 + qn, cmp);
for (int i = 1; i <= qn; i++) {
int L = q[i].l, R = q[i].r, T = q[i].t;
while (tn < T) addchange(++tn);
while (tn > T) delchange(tn--);
while (l > L) add(a[--l]);
while (r < R) add(a[++r]);
while (l < L) del(a[l++]);
while (r > R) del(a[r--]);
ans[q[i].id] = sum;
}
for (int i = 1; i <= qn; i++)
cout << ans[i] << "\n";
}
- 修改添加和删除的代码很重要..
- 可以树状数组写..
codes
const int maxn = 1e5 + 7;
int n, t, m, k, l, r;
char s[maxn], ch;
int ans[maxn], sum, num[200];
int qn;
struct query {
int l, r, id, t;
} q[maxn];
int tn;
struct change {
int pl;
char val, oval;
} c[maxn];
bool cmp(query a, query b) {
if (a.l / k != b.l / k) return a.l / k < b.l / k;
if (a.r / k != b.r / k) return a.r / k < b.r / k;
return a.t < b.t;
}
void add(char ch) {
num[ch]++;
if (num[ch] == 1)
sum++;
}
void del(char ch) {
num[ch]--;
if (num[ch] == 0)
sum--;
}
void addchange(int t) {
int pl = c[t].pl, val = c[t].val;
if (pl >= l && pl <= r)
add(val), del(s[pl]);
s[pl] = val;
}
void delchange(int t) {
int pl = c[t].pl, val = c[t].oval;
if (pl >= l && pl <= r)
add(val), del(s[pl]);
s[pl] = val;
}
void solve() {
cin >> (s + 1) >> m;
k = pow(strlen(s + 1), 2.0 / 3);
for (int i = 1; i <= m; i++) {
cin >> n;
if (n == 1) {
cin >> n >> ch;
c[++tn].pl = n, c[tn].val = ch, c[tn].oval = s[n];
s[n] = ch;
} else {
cin >> l >> r;
qn++, q[qn] = {l, r, qn, tn};
}
}
for (int i = tn; i >= 1; i--)
s[c[i].pl] = c[i].oval;
sort(q + 1, q + 1 + qn, cmp);
l = 1, r = 0, t = 0;
for (int i = 1; i <= qn; i++) {
int pl = q[i].l, pr = q[i].r, pt = q[i].t;
while (t < pt) addchange(++t);
while (t > pt) delchange(t--);
while (l > pl) add(s[--l]);
while (r < pr) add(s[++r]);
while (l < pl) del(s[l++]);
while (r > pr) del(s[r--]);
ans[q[i].id] = sum;
}
for (int i = 1; i <= qn; i++)
cout << ans[i] << endl;
}
我看见 你