#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,t,now,nowl,nowr;
int a[N],cnt[N];
bool ans[N];
struct number{int x,y,id;}num[N];
inline bool cmp(number a,number b)
{
if (a.x/t<b.x/t) return true;
if (a.x/t==b.x/t && a.y<b.y) return true;
return false;
}
inline int add(int pos)
{
cnt[a[pos]]++;
if (cnt[a[pos]]==1) now++;
}
inline int del(int pos)
{
cnt[a[pos]]--;
if (cnt[a[pos]]==0) now--;
}
int main(){
scanf("%d%d",&n,&m);
for (register int i=1; i<=n; ++i) scanf("%d",&a[i]);
t=(int)sqrt(n);
for (register int i=1; i<=m; ++i) scanf("%d%d",&num[i].x,&num[i].y),num[i].id=i;
sort(num+1,num+m+1,cmp);
for (register int i=1; i<=m; ++i)
{
// [nowl,nowr]区间内的now值已经算完了,如果nowl小于当前的左区间num[i].x,那么就得把 下标nowl 的贡献先减去,然后 nowl++
// 如果 nowl大于当前的左区间num[i].x ,那么,由于 下标nowl的贡献已经包括在now中了,且此刻now需要加上 下标nowl-1 的贡献
//所以先 nowl--,在加上这个下标的贡献
// nowr与nowl相同
while (nowl<num[i].x) del(nowl),nowl++;
while (nowl>num[i].x) nowl--,add(nowl);
while (nowr<num[i].y) nowr++,add(nowr);
while (nowr>num[i].y) del(nowr),nowr--;
if (now==num[i].y-num[i].x+1) ans[num[i].id]=true;
}
for (register int i=1; i<=m; ++i) if (ans[i]) puts("Yes"); else puts("No");
return 0;
}
带修莫队:
#include <bits/stdc++.h>
using namespace std;
const int N=5e4+5;
int n,m,sum,summ,nowl,nowr,nowt,now,t;
int a[N],cnt[1000005],ans[N];
char c;
struct number{int x,y,t,id;}num[N];
struct number2{int pos,val;}num2[N];
inline bool cmp(number a,number b)
{
if (a.x/t<b.x/t) return true;
if (a.x/t==b.x/t && a.y<b.y) return true;
if (a.x/t==b.x/t && a.y/t==b.y/t && a.t<b.t) return true;
return false;
}
inline void add(int pos)
{
cnt[a[pos]]++;
if (cnt[a[pos]]==1) now++;
}
inline void del(int pos)
{
cnt[a[pos]]--;
if (cnt[a[pos]]==0) now--;
}
inline void upt(int x)
{
if (nowl<=num2[x].pos && num2[x].pos<=nowr)
{
cnt[a[num2[x].pos]]--;
if (cnt[a[num2[x].pos]]==0) now--;
cnt[num2[x].val]++;
if (cnt[num2[x].val]==1) now++;
}
swap(a[num2[x].pos],num2[x].val);
}
int main(){
scanf("%d%d",&n,&m);
t=(int)sqrt(n);
for (register int i=1; i<=n; ++i) scanf("%d",&a[i]);
for (register int i=1; i<=m; ++i)
{
cin>>c;
if (c=='Q')
{
sum++;
scanf("%d%d",&num[sum].x,&num[sum].y);
num[sum].t=summ;
num[sum].id=sum;
}
else
{
summ++;
scanf("%d%d",&num2[summ].pos,&num2[summ].val);
}
}
sort(num+1,num+sum+1,cmp);
for (register int i=1; i<=sum; ++i)
{
while (nowl<num[i].x) del(nowl),nowl++;
while (nowl>num[i].x) nowl--,add(nowl);
while (nowr<num[i].y) nowr++,add(nowr);
while (nowr>num[i].y) del(nowr),nowr--;
while (nowt<num[i].t) nowt++,upt(nowt);
while (nowt>num[i].t) upt(nowt),nowt--;
ans[num[i].id]=now;
}
for (register int i=1; i<=sum; ++i) printf("%d\n",ans[i]);
return 0;
}
树上莫队:
#include <bits/stdc++.h>
using namespace std;
const int N=4e4+5,M=1e5+5;
int n,m,noww,t,len,u,v,x,y,id,LCA;
int nowl,nowr,now;
int a[N],b[N],b1[N],ans[M];
int d[N],p[N][21],bb[N<<1],ru[N],chu[N];
int sum[N],used[N];
int cnt,head[N];
struct edge{int next,to;}e[N<<1];
struct number{int x,y,id,lca;}num[M];
inline void add(int u,int v)
{
cnt++;
e[cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
inline bool cmp(number a,number b)
{
if (a.x/t<b.x/t) return true;
if (a.x/t==b.x/t && a.y<b.y) return true;
return false;
}
void dfs(int u,int fa)
{
id++; ru[u]=id; bb[id]=u;
for (register int i=1; (1<<i)<=d[u]; ++i) p[u][i]=p[p[u][i-1]][i-1];
for (register int i=head[u]; i; i=e[i].next)
if (e[i].to!=fa)
{
d[e[i].to]=d[u]+1;
p[e[i].to][0]=u;
dfs(e[i].to,u);
}
id++; chu[u]=id; bb[id]=u;
}
inline int lca(int a,int b)
{
if (d[a]>d[b]) swap(a,b);
for (register int i=20; i>=0; --i) if (d[b]-(1<<i)>=d[a]) b=p[b][i];
if (a==b) return a;
for (register int i=20; i>=0; --i)
if (p[a][i]==p[b][i]) continue;
else a=p[a][i],b=p[b][i];
return p[a][0];
}
inline void add(int pos)
{
sum[a[pos]]++;
if (sum[a[pos]]==1) now++;
}
inline void del(int pos)
{
sum[a[pos]]--;
if (sum[a[pos]]==0) now--;
}
inline void upt(int pos)
{
if (!used[bb[pos]]) add(bb[pos]); else del(bb[pos]);
used[bb[pos]]^=1;
}
int main(){
scanf("%d%d",&n,&m);
t=(int)sqrt(n);
for (register int i=1; i<=n; ++i) scanf("%d",&a[i]),b1[i]=a[i];
sort(b1+1,b1+n+1);
len=1; b[len]=b1[1]; noww=b1[1];
for (register int i=2; i<=n; ++i) if (b1[i]!=noww) len++,b[len]=b1[i],noww=b1[i];
for (register int i=1; i<=n; ++i) a[i]=lower_bound(b+1,b+len+1,a[i])-b;
for (register int i=1; i<n; ++i) scanf("%d%d",&u,&v),add(u,v),add(v,u);
dfs(1,0);
for (register int i=1; i<=m; ++i)
{
scanf("%d%d",&x,&y);
num[i].id=i;
if (d[x]>d[y]) swap(x,y);
LCA=lca(x,y);
if (LCA==x) num[i].x=ru[x],num[i].y=ru[y],num[i].lca=0;
// 如果两个点的lca为它们两个中的一个,那么 num[i].x就是深度小的点的ru, num[i].y就是深度大的点的ru
else num[i].x=chu[x],num[i].y=ru[y],num[i].lca=LCA;
//如果两个点的lca不为它们两个中的一个,那么num[i].x就是深度小的点的chu,num[i].y就是深度大的点的ru
}
sort(num+1,num+m+1,cmp);
nowl=1;
for (register int i=1; i<=m; ++i)
{
while (nowl<num[i].x) upt(nowl),nowl++;
while (nowl>num[i].x) nowl--,upt(nowl);
while (nowr<num[i].y) nowr++,upt(nowr);
while (nowr>num[i].y) upt(nowr),nowr--;
if (num[i].lca)
{
if (!used[num[i].lca]) add(num[i].lca); else del(num[i].lca);
used[num[i].lca]^=1;
}
ans[num[i].id]=now;
if (num[i].lca)
{
if (!used[num[i].lca]) add(num[i].lca); else del(num[i].lca);
used[num[i].lca]^=1;
}
}
for (register int i=1; i<=m; ++i) printf("%d\n",ans[i]);
return 0;
}