莫队
#include <bits/stdc++.h>
#define MAXN (50010)
#define ll long long
struct node{
int l, r, id;
}query[MAXN];
int BLOCKSIZE;
int n, m;
int c[MAXN], cnt[MAXN], bel[MAXN];
ll sum = 0;
bool cmp(const node &A, const node &B){
return bel[A.l] == bel[B.l] ? A.r < B.r : A.l < B.l;
}
void move(int pos, int val){
sum -= cnt[pos] * cnt[pos];
cnt[pos] += val;
sum += cnt[pos] * cnt[pos];
}
int main(){
scanf("%d%d", &n, &m);
BLOCKSIZE = (int)(ceil(sqrt(n)));
for(int i = 1; i <= n; ++ i){
scanf("%d", c + i);
bel[i] = (i - 1) / BLOCKSIZE + 1;
}
for(int i = 1; i <= m; ++ i){
int l, r;
scanf("%d%d", &l, &r);
query[i] = {l, r, i};
}
std::sort(query + 1, m + query + 1, cmp);
int l = 1, r = 0;
for(int i = 1; i <= m; ++ i){
for(; r < query[i].r; ++ r) move(c[r + 1], 1);
for(; r > query[i].r; -- r) move(c[r] , -1);
for(; l < query[i].l; ++ l) move(c[l] , -1);
for(; l > query[i].l; -- l) move(c[l - 1], 1);
}
return 0;
}
带修改莫队
#include <bits/stdc++.h>
#define MAXN (10010)
#define MAXR (1010)
#define MAXC (1000010)
struct qnode{ int l, r, id, t;}query[MAXN];
struct rnode{ int pos, col, pre;}revise[MAXR];
int BLOCKSIZE;
int n, m, cnt_r, cnt_q, sum;
int bel[MAXN], col[MAXN], num[MAXC], last[MAXN], ans[MAXN];
bool inseg[MAXN];
inline bool cmp(const qnode &A, const qnode &B){
return bel[A.l] == bel[B.l] ? (bel[A.r] == bel[B.r] ? A.t < B.t : A.r < B.r) :
A.l < B.l;
}
inline void cal(int pos){
if(inseg[pos]){
num[col[pos]] --;
sum -= !num[col[pos]];
}
else{
sum += !num[col[pos]];
num[col[pos]] ++;
}
inseg[pos] ^= 1;
}
inline void change(int pos, int c){
if(inseg[pos]){
cal(pos);
col[pos] = c;
cal(pos);
}
else col[pos] = c;
}
int main(){
scanf("%d%d", &n, &m);
BLOCKSIZE = (int)(ceil(pow(n, 2.0 / 3)));
for(int i = 1; i <= n; ++ i){
scanf("%d", col + i);
last[i] = col[i];
bel[i] = (i - 1) / BLOCKSIZE + 1;
}
for(int i = 1; i <= m; ++ i){
char op[3];
int l, r;
scanf("%s%d%d", op, &l, &r);
if(op[0] == 'R') revise[++ cnt_r] = {l, r, last[l]}, last[l] = r;
else query[++ cnt_q] = {l, r, cnt_q, cnt_r};
}
std::sort(query + 1, cnt_q + query + 1, cmp);
int l = 1, r = 0, t = 0;
for(int i = 1; i <= cnt_q; ++ i){
for(; t < query[i].t; ++ t) change(revise[t + 1].pos, revise[t + 1].col);
for(; t > query[i].t; -- t) change(revise[t] .pos, revise[t] .pre);
for(; r < query[i].r; ++ r) cal(r + 1);
for(; r > query[i].r; -- r) cal(r );
for(; l < query[i].l; ++ l) cal(l );
for(; l > query[i].l; -- l) cal(l - 1);
}
return 0;
}
树上莫队
#include <bits/stdc++.h>
#define MAXN (40010)
#define MAXM (100010)
#define MAXB (16)
struct qnode{ int u, v, id;}query[MAXM];
int BLOCKSIZE;
int n, m, now;
int col[MAXN], bel[MAXN], dep[MAXN];
int dfn[MAXN], tot, stack[MAXN], top, blockcnt;
int f[MAXN][MAXB], ans[MAXM];
int cnt[MAXN];
bool inans[MAXN];
std::vector<int> vec[MAXN];
bool cmp(const struct qnode &a, const struct qnode &b){
return bel[a.u] == bel[b.u] ? dfn[a.v] < dfn[b.v] : bel[a.u] < bel[b.u];
}
void dfs(int u, int fa){
dfn[u] = ++ tot;
int bottom = top;
for(auto v : vec[u]){
if(v == fa) continue;
f[v][0] = u;
dep[v] = dep[u] + 1;
for(int j = 0; f[v][j + 1] = f[f[v][j]][j]; ++ j);
dfs(v, u);
if(top - bottom >= BLOCKSIZE){
++ blockcnt;
while(top != bottom){
bel[stack[-- top]] = blockcnt;
}
}
}
stack[top ++] = u;
}
void change(int u){
if(inans[u]){
cnt[col[u]] --;
if(!cnt[col[u]]) now --;
}
else{
if(!cnt[col[u]]) now ++;
cnt[col[u]] ++;
}
inans[u] ^= 1;
}
void move(int u, int v){
int w = lca(u, v);
for(int i = u; i != w; i = f[i][0]){
change(i);
}
for(int i = v; i != w; i = f[i][0]){
change(i);
}
}
int main(){
scanf("%d%d", &n, &m);
BLOCKSIZE = n / (int)sqrt(m);
dfs(1, 0);
while(top){
bel[stack[-- top]] = blockcnt;
}
for(int i = 1; i <= m; ++ i){
scanf("%d%d", &query[i].u, &query[i].v);
if(dfn[query[i].u] > dfn[query[i].v]){
std::swap(query[i].u, query[i].v);
}
query[i].id = i;
}
std::sort(query + 1, m + query + 1, cmp);
int u = 1, v = 1;
for(int i = 1; i <= m; ++ i){
move(u, query[i].u);
move(v, query[i].v);
u = query[i].u;
v = query[i].v;
int w = lca(u, v);
change(w);
//get ans
change(w);
}
return 0;
}
带修改树上莫队
#include <bits/stdc++.h>
#define MAXN (100010)
#define MAXB (18)
#define ll long long
struct qnode{ int u, v, id, t;} query[MAXN];
struct rnode{ int pos, col, pre;} revise[MAXN];
int cnt_q, cnt_r, last[MAXN];
ll ans[MAXN], sum;
int cnt[MAXN];
bool inans[MAXN];
int n, m, q;
ll v[MAXN], w[MAXN], c[MAXN];
int bel[MAXN], tot, stack[MAXN], top, dep[MAXN];
int BLOCKSIZE, blockcnt;
int f[MAXN][MAXB];
std::vector<int> vec[MAXN];
bool cmp(const struct qnode &a, const struct qnode &b){
return bel[a.u] == bel[b.u] ? (bel[a.v] == bel[b.v] ? a.t < b.t : bel[a.v] < bel[b.v]) :
bel[a.u] < bel[b.u];
}
void dfs(int u, int fa){
int bottom = top;
for(auto v : vec[u]){
if(v == fa) continue;
f[v][0] = u;
dep[v] = dep[u] + 1;
for(int j = 0; f[v][j + 1] = f[f[v][j]][j]; ++ j);
dfs(v, u);
if(top - bottom >= BLOCKSIZE){
++ blockcnt;
while(top != bottom){
bel[stack[-- top]] = blockcnt;
}
}
}
stack[top ++] = u;
}
void change(int u){
int col = c[u];
if(inans[u]){
sum -= w[cnt[col]] * v[col];
cnt[col] --;
}
else{
cnt[col] ++;
sum += w[cnt[col]] * v[col];
}
inans[u] ^= 1;
}
void move(int u, int v){
int w = lca(u, v);
for(int i = u; i != w; i = f[i][0]){
change(i);
}
for(int i = v; i != w; i = f[i][0]){
change(i);
}
}
void moveTime(int u, int col){
if(inans[u]){
change(u);
c[u] = col;
change(u);
}
else c[u] = col;
}
int main(){
readin(n); readin(m); readin(q);
BLOCKSIZE = (int)(ceil(pow(n, 2.0 / 3)) * 0.5);
for(int i = 1; i <= m; ++ i){
readin(v[i]);
}
for(int i = 1; i <= n; ++ i){
readin(w[i]);
}
for(int i = 1; i < n; ++ i){
int a, b;
readin(a); readin(b);
vec[a].push_back(b);
vec[b].push_back(a);
}
dfs(1, 0);
while(top){
bel[stack[-- top]] = blockcnt;
}
for(int i = 1; i <= n; ++ i){
readin(c[i]);
last[i] = c[i];
}
for(int i = 1; i <= q; ++ i){
int t, x, y;
readin(t); readin(x); readin(y);
if(t){
query[++ cnt_q] = (qnode){x, y, cnt_q, cnt_r};
}
else{
revise[++ cnt_r] = (rnode){x, y, last[x]};
last[x] = y;
}
}
std::sort(query + 1, cnt_q + query + 1, cmp);
int u = 1, v = 1, t = 0;
for(int i = 1; i <= cnt_q; ++ i){
for(; t < query[i].t; ++ t) moveTime(revise[t + 1].pos, revise[t + 1].col);
for(; t > query[i].t; -- t) moveTime(revise[t] .pos, revise[t] .pre);
move(u, query[i].u);
move(v, query[i].v);
u = query[i].u;
v = query[i].v;
int w = lca(u, v);
change(w);
//get ans
change(w);
}
return 0;
}