P1494 [国家集训队] 小 Z 的袜子 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
普通莫队
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=50010;
ll a[N],cnt[N],ans,answer[N];
int n,m;
struct node{
ll l,r,id;
long long ans1,ans2;
}p[N];
int pos[N];
int cmp(struct node a,struct node b)
{
if(pos[a.l]!=pos[b.l]) return a.l<b.l;
return a.r>b.r;
}
void add(int p)
{
ans+=cnt[a[p]];
cnt[a[p]]++;
}
void del(int p)
{
cnt[a[p]]--;
ans-=cnt[a[p]];
}
ll gcb(long long a,long long b)
{
if(!b) return a;
return gcb(b,a%b);
}
int cmp1(struct node a,struct node b)
{
return a.id<b.id;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(cnt,0,sizeof cnt);
ans=0;
ll b=sqrt(n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
pos[i]=i/b;
}
for(int i=1;i<=m;i++)
{
scanf("%lld%lld",&p[i].l,&p[i].r);
p[i].id=i;
}
sort(p+1,p+m+1,cmp);
int l=1,r=0;
for(int i=1;i<=m;i++)
{
//ans=0;
while(l<p[i].l) del(l++);
while(l>p[i].l) add(--l);
while(r<p[i].r) add(++r);
while(r>p[i].r) del(r--);
p[i].ans1=ans;
p[i].ans2=(r-l+1)*(r-l)/2;
if(ans==0) {
p[i].ans2=1;
continue;
}
ll d=gcb(p[i].ans1,p[i].ans2);
p[i].ans1/=d;
p[i].ans2/=d;
}
sort(p+1,p+m+1,cmp1);
for(int i=1;i<=m;i++)
{
cout<<p[i].ans1<<"/"<<p[i].ans2<<endl;
}
}
return 0;
}
带修莫队
P1903 [国家集训队] 数颜色 / 维护队列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
普通mo队
//#include<iostream>
//#include<cstdio>
//#include<cstring>
//#include<cmath>
//#include<algorithm>
//using namespace std;
//const int N=500009;
//int n,m,a[N],cnt[N],pos[N],answer[N];
//int ans,k;
//typedef struct node{
// int l,r,id;
//}mo;
//mo p[N];
//int cmp(mo a,mo b)
//{
// if(pos[a.l]!=pos[b.l]) return a.l<b.l;//不在同一个区间
// else return pos[a.l]&1? a.r<b.r :b.r<a.r;//偶区间从小到大,奇区间从大到小
//}
//void add(int q)
//{
// ans-=cnt[a[q]]*cnt[a[q]];
// cnt[a[q]]++;
// ans+=cnt[a[q]]*cnt[a[q]];
//}
//void del(int q)
//{
// ans-=cnt[a[q]]*cnt[a[q]];
// cnt[a[q]]--;
// ans+=cnt[a[q]]*cnt[a[q]];
//}
//int main()
//{
// scanf("%d%d%d",&n,&m,&k);
// int b=n/sqrt(m*2/3);
// for(int i=1;i<=n;i++)
// scanf("%d",&a[i]),pos[i]=i/b;
// for(int i=1;i<=m;i++)
// {
// scanf("%d%d",&p[i].l,&p[i].r);
// p[i].id=i;
// }
// sort(p+1,p+m+1,cmp);
// int ll=1,rr=0;
// for(int i=1;i<=m;i++)
// {
// while(ll<p[i].l) del(ll++);
// while(ll>p[i].l) add(--ll);
// while(rr<p[i].r) add(++rr);
// while(rr>p[i].r) del(rr--);
// answer[p[i].id]=ans;
// }
// for(int i=1;i<=m;i++)
// cout<<answer[i]<<endl;
// return 0;
//}
//带修莫队
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=133400,M=1e6+10;
int cnt[M];
int a[N],answer[N];
int cntq;//记录询问操作
int cntp;//记录修改操作
int n,m,ans;
int block;
typedef struct node{
int l,r,id,t;
}mo;
typedef struct change{
int iid;//次序
int v;//要修改的值
}change;
mo q[N];
change p[N];
int cmp(mo a,mo b)
{
if(a.l/block!=b.l/block) return a.l<b.l;
else if(a.r/block!=b.r/block) return a.r<b.r;
return a.t<b.t;
}
void del(int i)
{
if(cnt[i]==1) ans--;
cnt[i]--;
}
void add(int i)
{
if(cnt[i]==0) ans++;
cnt[i]++;
}
void work(int i,int t)
{
if(q[i].l<=p[t].iid&&p[t].iid<=q[i].r){
del(a[p[t].iid]);
add(p[t].v);
}
swap(a[p[t].iid],p[t].v);
}
int main()
{
scanf("%d%d",&n,&m);
block=pow(n,(double)2/(double) 3);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
{
int x,y;
char op[5];
scanf("%s%d%d",op,&x,&y);
if(op[0]=='Q'){
cntq++;q[cntq]={x,y,cntq,cntp};
}
else{
cntp++;p[cntp]={x,y};
}
}
sort(q+1,q+cntq+1,cmp);
int ll=1,rr=0,tt=0;
for(int i=1;i<=cntq;i++)
{
while(ll>q[i].l) add(a[--ll]) ;
while(ll<q[i].l) del(a[ll++]);
while(rr>q[i].r) del(a[rr--]);
while(rr<q[i].r ) add(a[++rr]);
while(tt<q[i].t) work(i,++tt);
while(tt>q[i].t ) work(i,tt--);
answer[q[i].id]=ans;
}
for(int i=1;i<=cntq;i++)
cout<<answer[i]<<endl;
return 0;
}