小Z的袜子【莫队算法】

莫队算法最经典的题目吧。
其实莫队算法比较像暴力。(你不写曼哈顿最小生成树还说人家暴力(逃
好吧,其实我用的不是标准的莫队算法,而是类似一种分块的思想
将块的大小保持在sqrt(n),可以证明时间复杂度为O(n^1.5)
貌似可以根据已知[l,r]的信息是否可以O(1)的推出[l+1,r]和[l-1,r]的信息来判断是否试用莫队算法。
对于小Z的袜子这道题,我们先离线的排序询问,左端点第一关键字,右端点第二关键字
将1~n的块分好

block=(int)sqrt(n);
  for(int i=1;i<=n;i++)belong[i]=(i-1)/block+1;

排序

bool cmp(Node a,Node b){
  if(belong[a.l]==belong[b.l])return a.r<b.r;
  return a.l<b.l; 
}

一个区间内颜色相同的概率为:
设这个区间每个颜色的个数和记为a[i],则答案为 sigmaC(a[i],2)/C(r-l+1,2)
上下的2!可以约去,变为sigma(a[i] * (a[i]-1))/n*(n-1)
对于每次+1的操作会增加2*pre(a[i]) nowa[i]=pre[a[i]+1
发现如果使用nowa[i]-1的话会出现0*-1增加一是1*0的情况,所以决定不删去2!操作,直接加上prea[i],也就是ans+=后,a[i]++
同理可以分析出减法操作是 cnt减1后 ans-=
代码长这样:

    while(r<q[i].r)ans+=cnt[a[++r]]++;
    while(r>q[i].r)ans-=--cnt[a[r--]];
    while(l<q[i].l)ans-=--cnt[a[l++]];
    while(l>q[i].l)ans+=cnt[a[--l]]++;

其他需要注意的就是求个gcd,约分了。
并不清晰为甚么po大爷的分块跑500多秒,而我比他写的MMST还慢。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值