博客
注意:莫队的计算方式类似前缀和,所以查询区间
所以l只能这么算:
l=1;
while (l<q[i].l) minu(l++);
while (l>q[i].l) add(--l);
而不能:
while (l<q[i].l) minu(++l);
while (l>q[i].l) add(l--);
这是完全不一样的,会把q[i].l多算进去
1.BZOJ3781 小B的询问
#include<bits/stdc++.h>
using namespace std;
const int N=50002;
struct node{
int l,r,id;
}q[N];
int n,m,k,i,l,r,a[N],ans[N],cnt[N],cur,tim;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
inline void wri(int a){if(a<0)a=-a,putchar('-');if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(int a){wri(a);puts("");}
void add(int x){
cur+=(cnt[a[x]]++)<<1|1;
}
void minu(int x){
cur-=(--cnt[a[x]])<<1|1;
}
bool cmp(node a,node b){
return a.l/tim==b.l/tim?a.r<b.r:a.l<b.l;
}
int main(){
n=read();m=read();k=read();tim=sqrt(m);
for (i=1;i<=n;i++) a[i]=read();
for (i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+1,q+m+1,cmp);
l=1;
for (i=1;i<=m;i++){
while (l<q[i].l) minu(l++);
while (l>q[i].l) add(--l);
while (r<q[i].r) add(++r);
while (r>q[i].r) minu(r--);
ans[q[i].id]=cur;
}
for (i=1;i<=m;i++) wln(ans[i]);
}
2.BZOJ1878: [SDOI2009]HH的项链
#include<bits/stdc++.h>
using namespace std;
const int N=50002;
struct node{
int l,r,id;
}q[N<<2];
int n,m,i,l,r,a[N],ans[N<<2],cnt[N*20],cur,tim;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
inline void wri(int a){if(a<0)a=-a,putchar('-');if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(int a){wri(a);puts("");}
void add(int x){
cur+=!(cnt[a[x]]++);
}
void minu(int x){
cur-=!(--cnt[a[x]]);
}
bool cmp(node a,node b){
return a.l/tim==b.l/tim?a.r<b.r:a.l<b.l;
}
int main(){
n=read();
for (i=1;i<=n;i++) a[i]=read();
m=read();tim=sqrt(m);
for (i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+1,q+m+1,cmp);
l=1;
for (i=1;i<=m;i++){
while (l<q[i].l) minu(l++);
while (l>q[i].l) add(--l);
while (r<q[i].r) add(++r);
while (r>q[i].r) minu(r--);
ans[q[i].id]=cur;
}
for (i=1;i<=m;i++) wln(ans[i]);
}
3.BZOJ2038: [2009国家集训队]小Z的袜子(hose)
#include<bits/stdc++.h>
using namespace std;
const int N=50002;
typedef long long ll;
struct node{
int x,y,id;
}q[N];
int n,tim,l,r,cnt[N],i,a[N],m;
ll x,y,ans1[N],cur,G,ans2[N];
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
inline void wri(ll a){if(a<0)a=-a,putchar('-');if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(ll a){wri(a);puts("");}
void minu(int x){
cur-=(--cnt[a[x]]);
}
void add(int x){
cur+=(cnt[a[x]]++);
}
bool cmp(node a,node b){
return a.x/tim==b.x/tim?a.y<b.y:a.x<b.x;
}
int main(){
n=read();m=read();tim=(int)sqrt(m);
for (i=1;i<=n;i++) a[i]=read();
for (i=1;i<=m;i++) q[i].x=read(),q[i].y=read(),q[i].id=i;
sort(q+1,q+m+1,cmp);
l=1;
for (i=1;i<=m;i++){
while (l<q[i].x) minu(l++);
while (l>q[i].x) add(--l);
while (r<q[i].y) add(++r);
while (r>q[i].y) minu(r--);
ans1[q[i].id]=cur;
ans2[q[i].id]=r-l;
}
for (i=1;i<=m;i++){
x=ans1[i];y=ans2[i]*(ans2[i]+1)/2;
if (!x) puts("0/1");
else G=__gcd(x,y),wri(x/G),putchar('/'),wln(y/G);
}
}