题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2038

就是莫队算法;

先写了个分块,惨WA:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=;
int n,m,K,c[maxn],rk[maxn],cnt[maxn],cnt2[maxn],ct=,t,tmp[maxn];
ll sum,s;
struct N{int l,r;ll ans,ans2;}q[maxn];
int rd()
{
int ret=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return ret;
}
bool cmp(int x,int y){return q[x].l<q[y].l;}
bool cmp2(int x,int y){return q[x].r<q[y].r;}
int C(int x){return x*(x-)/;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void yf(N &x)//&
{
ll k=gcd(x.ans2,x.ans);
x.ans/=k;x.ans2/=k;
}
void solve(int k)
{
sort(tmp+,tmp+t+,cmp2);
sum=;
memset(cnt,,sizeof cnt);
int L=k*K,R=L+;
for(int i=;i<=t;i++)
{
memset(cnt2,,sizeof cnt2);
while(R<=q[tmp[i]].r)
{
sum+=cnt[c[R]];cnt[c[R]]++;R++;
}
s=sum;
for(int j=L;j>=q[tmp[i]].l;j--)
{
s+=cnt[c[j]]+cnt2[c[j]];cnt2[c[j]]++;
}
q[tmp[i]].ans=s;
q[tmp[i]].ans2=C(q[tmp[i]].r-q[tmp[i]].l+);
yf(q[tmp[i]]);
}
}
int main()
{
n=rd();m=rd();K=sqrt(n);
for(int i=;i<=n;i++)c[i]=rd();
for(int i=;i<=m;i++)q[i].l=rd(),q[i].r=rd(),rk[i]=i;
sort(rk+,rk+m+,cmp);
for(int i=;(i-)*K<n;i++)
{
t=;
while(q[rk[ct]].l<=i*K&&ct<=m)tmp[++t]=rk[ct],ct++;
solve(i);
}
for(int i=;i<=m;i++)
printf("%lld/%lld\n",q[i].ans,q[i].ans2);
return ;
}

然后看了看题解,竟然是另一种做法,处理了一下式子:https://www.cnblogs.com/MashiroSky/p/5914637.html

所以抄了一下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=;
int n,m,K,c[maxn],cnt[maxn],blk[maxn];
ll ans;
struct N{int l,r,bh;ll a,b;}q[maxn];
int rd()
{
int ret=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return ret;
}
bool cmp(N x,N y){return blk[x.l]==blk[y.l]?x.r<y.r:blk[x.l]<blk[y.l];}
bool cmp2(N x,N y){return x.bh<y.bh;}
ll gcd(ll a,ll b){return a%b==?b:gcd(b,a%b);}
void update(int x,int val)
{
ans-=cnt[c[x]]*cnt[c[x]];
cnt[c[x]]+=val;
ans+=cnt[c[x]]*cnt[c[x]];
}
int main()
{
n=rd();m=rd();K=sqrt(n);
for(int i=;i<=n;i++)c[i]=rd(),blk[i]=(i-)/K+;;
for(int i=;i<=m;i++)q[i].l=rd(),q[i].r=rd(),q[i].bh=i;
sort(q+,q+m+,cmp);
for(int i=,l=,r=;i<=m;i++)
{
while(l<q[i].l)update(l,-),l++; while(l>q[i].l)update(l-,),l--;
while(r<q[i].r)update(r+,),r++; while(r>q[i].r)update(r,-),r--;
if(q[i].l==q[i].r)
{
q[i].a=;q[i].b=;continue;
}
q[i].a=(ll)ans-(r-l+); q[i].b=(ll)(r-l+)*(r-l);//(ll)!!!
ll k=gcd(q[i].a,q[i].b);//把分子放前面,万一分子是0
q[i].a/=k; q[i].b/=k;
}
sort(q+,q+m+,cmp2);
for(int i=;i<=m;i++)
printf("%lld/%lld\n",q[i].a,q[i].b);
return ;
}

...

然后又看到一篇博客:https://www.cnblogs.com/xuwangzihao/p/5199174.html

我的想法还是可以的嘛,加入一个点就是增加了之前有的这种点个数那么多的点对,所以维护点的个数即可;

主要是这个题不用严格按照分块来做,只是按分块排一下序就可以保证时间复杂度了,所以 l 和 r 直接全局移动就可以;

这样的话代码突然变得好优美...说到底自己那样的分块还是写得太丑,都不能保证正确呢...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=;
int n,m,K,c[maxn],cnt[maxn],blk[maxn];
ll ans;
struct N{int l,r,bh;ll a,b;}q[maxn];
int rd()
{
int ret=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return ret;
}
bool cmp(N x,N y){return blk[x.l]==blk[y.l]?x.r<y.r:blk[x.l]<blk[y.l];}
bool cmp2(N x,N y){return x.bh<y.bh;}
ll C(ll x){return x*(x-)/;}
ll gcd(ll a,ll b){return a%b==?b:gcd(b,a%b);}
void pop(int x){cnt[c[x]]--;ans-=cnt[c[x]];}//注意顺序
void push(int x){ans+=cnt[c[x]];cnt[c[x]]++;}
int main()
{
n=rd();m=rd();K=sqrt(n);
for(int i=;i<=n;i++)c[i]=rd(),blk[i]=(i-)/K+;
for(int i=;i<=m;i++)q[i].l=rd(),q[i].r=rd(),q[i].bh=i;
sort(q+,q+m+,cmp);
for(int i=,l=,r=;i<=m;i++)
{
while(l<q[i].l)pop(l),l++;
while(l>q[i].l)push(l-),l--;
while(r<q[i].r)push(r+),r++;
while(r>q[i].r)pop(r),r--;
q[i].a=ans;
q[i].b=C(r-l+);
ll k=gcd(q[i].a,q[i].b);//把分子放前面,万一分子是0
q[i].a/=k; q[i].b/=k;
}
sort(q+,q+m+,cmp2);
for(int i=;i<=m;i++)
printf("%lld/%lld\n",q[i].a,q[i].b);
return ;
}

bzoj2038 小Z的袜子(hose)——莫队算法的更多相关文章

  1. BZOJ2038: [2009国家集训队]小Z的袜子(hose) -- 莫队算法 ,,分块

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 3577  Solved: 1652[Subm ...

  2. [BZOJ2038] [2009国家集训队]小Z的袜子(hose) 莫队算法练习

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 10299  Solved: 4685[Sub ...

  3. BZOJ2038 小Z的袜子 (莫队算法)

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=2038 专题练习: http://acm.hust.edu.cn/vjudge/conte ...

  4. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7687  Solved: 3516[Subm ...

  5. kyeremal-bzoj2038-[2009国家集训队]-小z的袜子(hose)-莫队算法

    id=2038">bzoj2038-[2009国家集训队]-小z的袜子(hose) F.A.Qs Home Discuss ProblemSet Status Ranklist Con ...

  6. 【bzoj2038】[2009国家集训队]小Z的袜子(hose) 莫队算法

    原文地址:http://www.cnblogs.com/GXZlegend/p/6803860.html 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终 ...

  7. [bzoj2038][2009国家集训队]小Z的袜子(hose)——莫队算法

    Brief Description 给定一个序列,您需要处理m个询问,每个询问形如[l,r],您需要回答在区间[l,r]中任意选取两个数相同的概率. Algorithm Design 莫队算法入门题目 ...

  8. BZOJ2038: [2009国家集训队]小Z的袜子(hose) 莫队算法

    要使用莫队算法前提 ,已知[l,r]的答案,要能在logn或者O(1)的时间得到[l+1,r],[l-1,r],[l,r-1],[l,r+1],适用于一类不修改的查询 优美的替代品——分块将n个数分成 ...

  9. Bzoj 2038---[2009国家集训队]小Z的袜子(hose) 莫队算法

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色 ...

随机推荐

  1. SeLion数据驱动中遇到的问题,以及解决方案

    问题描述: 使用selion框架数据驱动时,总是test ignored. 解决方案: 把这个dataprovider方法拿出来做单元测试.有详细报错. 问题1:使用wps保存,poi包只能解析xls ...

  2. 【HDOJ6330】Visual Cube(模拟)

    题意: 思路: import java.util.Scanner; public class Main { public static void main(String args[]) { Scann ...

  3. 【BZOJ2733】永无乡(线段树,启发式合并)

    题意:支持合并,求块内K小数 对于 100%的数据 n≤100000,m≤n,q≤300000 思路:对于每一个块建立一棵动态开点的线段树,暴力(启发式?)合并后二分下就行了 merge用函数的方式写 ...

  4. 命令行模式直接下载jar包到本地库

    命令行下,直接使用  dependency:get -DrepoUrl=仓库地址 -Dartifact=groupId:artifactId:version[:packaging][:classifi ...

  5. 7.1——函数的定义,参数传递,return语句

    函数的定义: (1)函数体是一个作用域,函数体是一个语句块,定义了函数的具体操作 (2)函数的形参类似于局部变量,只是区别是它是在函数的形参列表中定义的. (3)C++是一种静态强类型语言,对于每一次 ...

  6. Codeforces 618C(计算几何)

    C. Constellation time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  7. GOF 23种设计模式目录

    经典的gof 23种设计模式,目录大纲查看. 1. Singleton(单例模式) 保证一个类只有一个实例,并提供访问它的全局访问点. 2. Abstract Factory(抽象工厂模式) 提供一个 ...

  8. D. Babaei and Birthday Cake---cf629D(最长上升子序列和+线段树优化)

    http://codeforces.com/problemset/problem/629/D 题目大意: 我第一反应就是求最长上升子序列和  但是数值太大了  不能直接dp求  可以用线段树优化一下 ...

  9. 简单使用SOCKET,TCP,UDP模式之间的通信

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络OSI模型中, ...

  10. HDTVI,HDCVI

    HDTVI是海康的同轴高清标准,HDCVI是大华的同轴高清标准,二者互相不兼容.