##借鉴的博客
莫队
const int maxn = 1000000+100;
int n,m,k,len,ans;
int num[maxn],cnt[maxn],a[maxn];
struct query{
int l,r,in,id;
I bool operator <(const query &a)const
{return (in^a.in)?in<a.in:((in&1)?r<a.r:r>a.r);}
}q[maxn];
signed main(){
read(n);
int QAQ=pow(n,0.6);
len=QAQ*QAQ*QAQ;
for(R int *S=a,*T=a+n;S!=T;)read(*++S);
read(m);
int x,y;
FOR(i,1,m)
read(q[i].l),read(q[i].r),
q[i].in=(q[i].l-1)/len+1,
q[i].id=i;
sort(q+1,q+1+m);
int l=1,r=0;
FOR(i,1,m){
int x=q[i].l,y=q[i].r;
while(l<x)ans-=(!--cnt[a[l++]]);
while(l>x)ans+=(!cnt[a[--l]]++);
while(r<y)ans+=(!cnt[a[++r]]++);
while(r>y)ans-=(!--cnt[a[r--]]);
num[q[i].id]=ans;
}
for(R int *S=num,*T=num+m;S!=T;)write(*++S),pc('\n');
flush();
return 0;
}
待修莫队:
const int maxn=2*1e6+10;
int n,m,a[maxn],in[maxn];
struct Query{
int x,y,pre,id;
}Q[maxn];
struct Change{
int pos,val;
}C[maxn];
int Qnum=0,Cnum=0;
int cnt[maxn],ans=0,base,out[maxn];
I int cmp(const Query &a,const Query &b){
if(a.x!=b.x)return in[a.x]<in[b.x];
if(a.y!=b.x)return in[a.y]<in[b.y];
return a.pre<b.pre;
}
I void work(int now,int i){
if(C[now].pos>=Q[i].x&&C[now].pos<=Q[i].y){
if(--cnt[a[C[now].pos]]==0)ans--;
if(++cnt[C[now].val]==1)ans++;
}
swap(C[now].val,a[C[now].pos]);
}
I void MoQueue(){
int l=1,r=0,now=0;
FOR(i,1,Qnum){
while(l<Q[i].x)ans-=!--cnt[a[l++]];
while(l>Q[i].x)ans+=!cnt[a[--l]]++;
while(r<Q[i].y)ans+=!cnt[a[++r]]++;
while(r>Q[i].y)ans-=!--cnt[a[r--]];
while(now<Q[i].pre)work(++now,i);
while(now>Q[i].pre)work(now--,i);
out[Q[i].id]=ans;
}
FOR(i,1,Qnum)
write(out[i]),pc('\n');
}
signed main(){
read(n),read(m);
base=pow(n,(double)2/(double)3);
FOR(i,1,n)read(a[i]),in[i]=(i-1)/base+1;
while(m--){
if(Read()){
read(Q[++Qnum].x),
read(Q[Qnum].y),
Q[Qnum].pre=Cnum,
Q[Qnum].id=Qnum;
}else{
read(C[++Cnum].pos);
read(C[Cnum].val);
}
}
sort(Q+1,Q+Qnum+1,cmp);
MoQueue();
flush();
return 0;
}
树上莫队:
//a,cnt,first,last,ans,belong,inp,vis,ncnt,l,r,now,size,bnum莫队相关
int a[maxn],cnt[maxn],first[maxn],last[maxn];
int ans[maxn],belong[maxn],inp[maxn],vis[maxn];
int ord[maxn],val[maxn],head[maxn],dep[maxn];
int fa[maxn][21],ecnt,ncnt,l=1,r,now,len,bnum,n,m;
// ord Euler-pos first Euler->begin last Euler->end;
struct edge{
int v,n;
I edge(const int &vv=0,const int & nn=0):v(vv),n(nn){}
}e[maxn];
void add(int u,int v){
e[++ecnt]=edge(v,head[u]),head[u]=ecnt;
e[++ecnt]=edge(u,head[v]),head[v]=ecnt;
}
void dfs(int u){
ord[++ncnt]=u;
first[u]=ncnt;
for(int ee=head[u],v;v=e[ee].v,ee;ee=e[ee].n)
if(v!=fa[u][0]){
dep[v]=dep[u]+1;
fa[v][0]=u;
for(int i=1;(1<<i)<=dep[v];++i)fa[v][i]=fa[fa[v][i-1]][i-1];
dfs(v);
}
ord[++ncnt]=u;
last[u]=ncnt;
}
int get_lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
for(int i=20;i+1;--i)
if(dep[u]-(1<<i)>=dep[v])u=fa[u][i];
if(u==v)return u;
for(int i=20;i+1;--i)
if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
struct query{
int l,r,lca,id;
}q[maxn];
int cmp(const query &a,const query &b){
return (belong[a.l]^belong[b.l])?(belong[a.l]<belong[b.l]):((belong[a.l]&1)?a.r<b.r:a.r>b.r);
}
I void work(int pos){
vis[pos]?
now-=!--cnt[val[pos]]:
now+=!cnt[val[pos]]++;
vis[pos]^=1;
}
signed main(){
read(n),read(m);
FOR(i,1,n)read(val[i]),inp[i]=val[i];
sort(inp+1,inp+1+n);
int tot=unique(inp+1,inp+1+n)-inp-1;
FOR(i,1,n)
val[i]=lower_bound(inp+1,inp+tot+1,val[i])-inp;
int x,y;
FOR(i,1,n-1)read(x),read(y),add(x,y);
dep[1]=1;dfs(1);
len=sqrt(ncnt),bnum=ceil((double)ncnt/len);
FOR(i,1,bnum)
for(int j=len*(i-1)+1;j<=i*len;++j)
belong[j]=i;
FOR(i,1,m){
int x,y,lca;
read(x),read(y),lca=get_lca(x,y);
if(first[x]>first[y])swap(x,y);
if(x==lca){
q[i].l=first[x];
q[i].r=first[y];
}else{
q[i].l=last[x];
q[i].r=first[y];
q[i].lca=lca;
}
q[i].id=i;
}
sort(q+1,q+1+m,cmp);
FOR(i,1,m){
int ql=q[i].l,qr=q[i].r,lca=q[i].lca;
while(l<ql)work(ord[l++]);
while(l>ql)work(ord[--l]);
while(r<qr)work(ord[++r]);
while(r>qr)work(ord[r--]);
if(lca)work(lca);
ans[q[i].id]=now;
if(lca)work(lca);
}
FOR(i,1,m)write(ans[i]),pc('\n');
flush();
return 0;
}
回滚莫队:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define maxn 100100
#define maxb 5050
#define ll long long
int aa[maxn], typ[maxn], cnt[maxn], cnt2[maxn], belong[maxn], lb[maxn], rb[maxn], inp[maxn];
ll ans[maxn];
struct query {
int l, r, id;
} q[maxn];
int n, m, size, bnum;
#define isdigit(x) ((x) >= '0' && (x) <= '9')
inline int read() {
int res = 0;
char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) res = (res << 1) + (res << 3) + (c ^ 48), c = getchar();
return res;
}
int cmp(query a, query b) {
return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : a.r < b.r;
}
int main() {
n = read(), m = read();
size = sqrt(n);
bnum = ceil((double) n / size);
for(int i = 1; i <= bnum; ++i) {
lb[i] = size * (i - 1) + 1;
rb[i] = size * i;
for(int j = lb[i]; j <= rb[i]; ++j) belong[j] = i;
}
rb[bnum] = n;
for(int i = 1; i <= n; ++i) inp[i] = aa[i] = read();
sort(inp + 1, inp + n + 1);
int tot = unique(inp + 1, inp + n + 1) - inp - 1;
for(int i = 1; i <= n; ++i) typ[i] = lower_bound(inp + 1, inp + tot + 1, aa[i]) - inp;
for(int i = 1; i <= m; ++i) {
q[i].l = read(), q[i].r = read();
q[i].id = i;
}
sort(q + 1, q + m + 1, cmp);
int i = 1;
for(int k = 0; k <= bnum; ++k) {
int l = rb[k] + 1, r = rb[k];
ll now = 0;
memset(cnt, 0, sizeof(cnt));
for( ; belong[q[i].l] == k; ++i) {
int ql = q[i].l, qr = q[i].r;
ll tmp;
if(belong[ql] == belong[qr]) {
tmp = 0;
for(int j = ql; j <= qr; ++j) cnt2[typ[j]] = 0;
for(int j = ql; j <= qr; ++j) {
++cnt2[typ[j]]; tmp = max(tmp, 1ll * cnt2[typ[j]] * aa[j]);
}
ans[q[i].id] = tmp;
continue;
}
while(r < qr) {
++r; ++cnt[typ[r]]; now = max(now, 1ll * cnt[typ[r]] * aa[r]);
}
tmp = now;
while(l > ql){
--l; ++cnt[typ[l]]; now = max(now, 1ll * cnt[typ[l]] * aa[l]);
}
ans[q[i].id] = now;
while(l < rb[k] + 1) {
--cnt[typ[l]];
l++;
}
now = tmp;
}
}
for(int i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
return 0;
}