一道简单的莫队算法题:
https://vjudge.net/contest/171364#problem/I
莫队的一般写法:
// CodeForces 86D
#include
#define pb push_back
#define mp make_pair
using namespace std;
const int maxn=2e5+7;
typedef long long ll;
struct Mo{
int l,r,t,id;
}p[maxn];
ll a[maxn];
ll f[1000007];
ll ans[maxn];
int n,Q;
ll now=0;
bool operator<(const Mo &a,const Mo &b)
{
if(a.t==b.t) return a.rreturn a.tvoid dec(int x)
{
ll v=a[x];
now+=(-2*f[v]+1)*v;
f[v]--;
}
void add(int x)
{
ll v=a[x];
now+=(2*f[v]+1)*v;
f[v]++;
}
int main()
{
int i,j,k,T;
scanf("%d%d",&n,&Q);
for(i=1;i<=n;++i)
{
scanf("%lld",&a[i]);
}
int q=700;
for(i=1;i<=Q;++i)
{
scanf("%d%d",&p[i].l,&p[i].r);
p[i].t=p[i].l/q;
p[i].id=i;
}
sort(p+1,p+Q+1);
int l=1,r=0;
for(i=1;i<=Q;++i)
{
while(lwhile(l>p[i].l) add(--l);
while(r
while(r>p[i].r) dec(r--);
ans[p[i].id]=now;
}
for(i=1;i<=Q;++i)
{
printf("%I64d\n",ans[i]);
}
return 0;
}
稍难一点的莫队(莫队+分块)
http://acm.uestc.edu.cn/#/problem/show/1753
别人的题解:
http://hzwer.com/5749.html
我的代码:
// UESTC - 1753
#include
#define pb push_back
#define mp make_pair
using namespace std;
const int maxn=1e5+7,maxm=1e6+7;
typedef long long ll;
//快速读入
inline void read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;
n=q*w;
}
//快速输出
inline void write(int x){
static const int maxlen=100;
static char s[maxlen];
if (x<0) { putchar('-'); x=-x;}
if(!x){ putchar('0'); return; }
int len=0; for(;x;x/=10) s[len++]=x % 10+'0';
for(int i=len-1;i>=0;--i) putchar(s[i]);
}
struct Mo{
int l,r,id,a,b;
}p[maxm];
int ans[maxm];
int n,m;
struct Part{
int l,r,num;
}part[maxn];
int f[maxn],s[maxn];
int ntop[maxn];
int q;
bool operator<(const Mo &a,const Mo &b)
{
if(a.l/q==b.l/q) return a.rreturn a.l/qvoid add(int x)
{
int v=s[x];
f[v]++;
if(f[v]==1) part[ntop[v]].num++;
}
void dec(int x)
{
int v=s[x];
f[v]--;
if(f[v]==0) part[ntop[v]].num--;
}
int get_ans(int l,int r)
{
int L=ntop[l],R=ntop[r];
int res=0,i;
if(L==R)
{
for(i=l;i<=r;++i)
{
if(f[i])
res++;
}
return res;
}
for(i=L+1;i<=R-1;++i)
res+=part[i].num;
for(i=l;i<=part[L].r;++i)
if(f[i]) res++;
for(i=part[R].l;i<=r;++i)
if(f[i]) res++;
return res;
}
void doit_mo()
{
int l=1,r=0;
for(int i=1;i<=m;++i)
{
while(lwhile(l>p[i].l) add(--l);
while(r
while(r>p[i].r) dec(r--);
ans[p[i].id]=get_ans(p[i].a,p[i].b);
}
}
int main()
{
int i,j,k,T;
read(n);read(m);
q=sqrt(n);
for(i=1;i<=n;++i)
{
ntop[i]=(i-1)/q+1;
}
for(i=1;i<=n;i+=q)
{
part[ntop[i]].l=i;
part[ntop[i]].r=i+q-1;
}
for(i=1;i<=n;++i)
{
read(s[i]);
}
for(i=1;i<=m;++i)
{
read(p[i].l);
read(p[i].r);
read(p[i].a);
read(p[i].b);
p[i].id=i;
}
sort(p+1,p+1+m);
doit_mo();
for(i=1;i<=m;++i)
write(ans[i]),putchar('\n');
/*
for(i=1;i<=m;++i)
printf("%d\n",ans[i]);
*/
return 0;
}
————————
关于分块的方法:
用刘大爷的话说,第一种满足基本复杂度,第二种在m很大时更优
————————
当带上修改时:
http://blog.csdn.net/hzj1054689699/article/details/51866615