题目: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. [luoguP2962] [USACO09NOV]灯Lights(高斯消元 + dfs)

    传送门 先进行高斯消元 因为要求最少的开关次数,那么: 对于关键元,我们可以通过带入消元求出, 对于自由元,我们暴力枚举,进行dfs,因为只有开关两种状态,0或1 #include <cmath ...

  2. [bzoj1787][Ahoi2008]Meet 紧急集合(lca)

    传送门 可以看出,三个点两两之间的lca会有一对相同,而另一个lca就是聚集点. 然后搞搞就可以求出距离了. ——代码 #include <cstdio> #include <cst ...

  3. Codeforces 892 A.Greed

    A. Greed time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  4. 【HDOJ6300】Triangle Partition(极角排序)

    题意:给定3n个点,保证没有三点共线,要求找到一组点的分组方案使得它们组成的三角形之间互不相交. n<=1e3 思路:以y为第一关键字,x为第二关键字,按x递减,y递增排序 #include&l ...

  5. 我的Github,个人博客

    Github: github.com/wuxinwei 个人博客: blog.wuxinwei.org

  6. java HashMap的使用

    java HashMap的使用 import java.util.HashMap; import java.util.Iterator; public class WpsklHashMap { pub ...

  7. git修改commit message及vi编辑器的简单使用

    1.修改commit信息 git commit --amend 2.进入vi编辑器修改 ‘i’进入insert模式,输入文字: ‘esc’回到命令模式,删除文字,移动光标: ‘:’进入底行模式,‘wq ...

  8. 【Java源码】集合类-ArrayList

    一.类继承关系 public class ArrayList<E> extends AbstractList<E> implements List<E>, Rand ...

  9. poj——3177Redundant Paths

    poj——3177Redundant Paths      洛谷—— P2860 [USACO06JAN]冗余路径Redundant Paths Time Limit: 1000MS   Memory ...

  10. 多校训练hdu --Nice boat(线段树,都是泪)

    Nice boat Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total ...