莫队-小Z的袜子
----普通莫队
首先
清楚概率怎么求
假设我们要求从区间l到r中拿出一对袜子的概率
sum[i]为第i种袜子在l到r中的数量
$$\frac{\sum_{i=l}^{r} {[sum[i] \times (sum[i]-1)]}}{ (r-l+1) \times {(r-l)}}\qquad$$
转化一下可以得到
$$\frac{\sum_{i=l}^{r} {sum[i]^{2}}-(r-l+1)}{ (r-l+1)\times {(r-l)}}\qquad$$
普通莫队是一种离线算法 并且充分利用上一个得到的答案来求得当前询问的答案
怎么由上一个答案来得到当前的答案呢?
设
$$ans=\sum_{i=l}^{r} {sum[i]^{2}}$$
即分母的一部分(减去(r-l+1)即可得到分母)
现在要求[l+1,r]这个区间的答案
若第l只袜子的编号为x 则只有sum[x]减少了1
更新ans的操作如下:
ans-=sum[x]*sum[x];
sum[x]-=1;
ans+=sum[x]*sum[x]
即:减去从前对答案的贡献 加上现在的贡献
求[l-1,r],[l,r-1],[l,r+1]的做法类比可得
整理一下可以得到change函数
//x为新增加或减少的点
//若为新增加的点 如l指针左移和r指针右移 则w=1
//反之 w=-1
/*例子:求[l-1,r] change(l,-1)
求[l,r+1] change(r+1,1) ……*/
change(int x,int w)
{
ans-=sum[x]*sum[x];sum[x]+=w;ans+=sum[x]*sum[x];
}
为了使l和r指针尽可能少的移动(优化时间)
我们需要给所有的问题的l和r排序
构造cmp函数
要用分块
将整个长度为n的序列分为sqrt(n)块
cmp为:若l与r在同一块中 则按照l从小到大排序
否则 按照r从小到大排序
这样l指针每次最多跳2*(n/sqrt(n))次
最后求gcd 即可
还要记得l==r的特判
一种优秀的gcd求法
//普通gcd
int gcd(int x,int y)
{
return y==0?x:gcd(y,x%y);
}
其实可以看成是把x赋值为x%y 再调换x,y的位置 求gcd(x,y)
假设我们要调换a,b的值
//普通做法:
int tmp;tmp=a;a=b;b=tmp; //其实可以利用位运算 异或
x^=y;y^=x;x^=y; /* 第一步:x=x^y
第二步:y=y^(x^y) 由于y^y=0 所以 y=x
第三步:x=(x^y)^x 同理可得 x=y
*/
可以得到gcd函数
ll gcd(ll a,ll b)
{
while(b^=a^=b^=a%=b);return a;
}
//从右至左运算
分析over
code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long
#define yes(i,a,b) for(register int i=a;i<=b;i++)
#define M 50010
using namespace std;
int n,m,tot,len;
ll ans,f_ans[M][2],sum[M];
int c[M],be[M];
struct node {int l,r,id;} q[M];
bool cmp(node x,node y)
{
if(be[x.l]==be[y.l]) return x.r<y.r;
return x.l<y.l;
}
void change(int x,int w)
{
ans-=(ll)(sum[c[x]]*sum[c[x]]);sum[c[x]]+=w;ans+=(ll)(sum[c[x]]*sum[c[x]]);
}
ll gcd(ll a,ll b)
{
while(b^=a^=b^=a%=b);return a;
}
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%d%d",&n,&m);
len=sqrt(n);
yes(i,1,n) scanf("%d",&c[i]),be[i]=i/len+1;
yes(i,1,m) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
sort(q+1,q+m+1,cmp);
int l=1,r=0;
yes(i,1,m)
{
while(l<q[i].l) change(l,-1),l++;
while(l>q[i].l) change(l-1,1),l--;
while(r<q[i].r) change(r+1,1),r++;
while(r>q[i].r) change(r,-1),r--;
ll ans1,ans2;
ans1=ans-(ll)(q[i].r-q[i].l+1);ans2=(ll)(q[i].r-q[i].l+1)*(q[i].r-q[i].l);
if(ans1==0) ans2=1;
else
{
ll g=gcd(ans2,ans1);
ans1/=g;ans2/=g;
}
f_ans[q[i].id][0]=ans1;f_ans[q[i].id][1]=ans2;
}
yes(i,1,m) printf("%lld/%lld\n",f_ans[i][0],f_ans[i][1]);
return 0;
}
莫队-小Z的袜子的更多相关文章
- 初识莫队——小Z的袜子
以前一直觉得莫队是多么高大上的一种算法,然而仔细看了下发现其实并不复杂,实质上就是技巧性的暴力美学. 在我看来莫队是一种分块排序后降低复杂度的算法,当答案可以通过左右端点一个一个移动维护出来的时候就可 ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 7687 Solved: 3516[Subm ...
- 莫队算法 2038: [2009国家集训队]小Z的袜子(hose)
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2038 2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 ...
- BZOJ-2038 小Z的袜子(hose) 莫队算法
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MB Submit: 5573 Solved: 2568 [Subm ...
- BZOJ 2038 [2009国家集训队]小Z的袜子 莫队
2038: [2009国家集训队]小Z的袜子(hose) 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Descriptionw ...
- Bzoj 2038: [2009国家集训队]小Z的袜子(hose) 莫队,分块,暴力
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 5763 Solved: 2660[Subm ...
- BZOJ2038: [2009国家集训队]小Z的袜子(hose) -- 莫队算法 ,,分块
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 3577 Solved: 1652[Subm ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) ( 莫队 )
莫队..先按sqrt(n)分块, 然后按块的顺序对询问排序, 同块就按右端点排序. 然后就按排序后的顺序暴力求解即可. 时间复杂度O(n1.5) --------------------------- ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&&学习笔记】
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 9894 Solved: 4561[Subm ...
随机推荐
- (待修莫队 没过! 抽空在检查)Dynamic len(set(a[L:R])) UVA - 12345
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...
- 2017/10 冲刺NOIP集训记录:暁の水平线に胜利を刻むのです!
前几次集训都没有记录每天的点滴……感觉缺失了很多反思的机会. 这次就从今天开始吧!不能懈怠,稳步前进! 2017/10/1 今天上午进行了集训的第一次考试…… 但是这次考试似乎是近几次我考得最渣的一次 ...
- Day22-Django之缓存
由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5 ...
- c++11 类默认函数的控制:"=default" 和 "=delete"函数
c++11 类默认函数的控制:"=default" 和 "=delete"函数 #define _CRT_SECURE_NO_WARNINGS #include ...
- 洛谷 P1436 棋盘分割 解题报告
P1436 棋盘分割 题目描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的两部分中的任意一块继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共 ...
- ZABBIX 3.4 监控Nginx 状态(七)
一.环境准备 1.在nginx的配置文件中,添加status配置 location /nginx_status { stub_status on; ...
- VIM 模板
Vim实现自动加载模版功能可以有很多的方法,比如利用插件和AutoCmd等.根据文件名自动加载模板的功能利用网上某大牛自己写的插件实现,我针对Java代码进行简单地修改,以实现模板中的Java主类类名 ...
- poj 2396 Budget
一个m行n列的矩阵,给出每行每列中元素的和,以及对一些格子的大小限制,求一个可行方案,输出矩阵. 大小限制形如:严格大于i,严格小于i,等于i. 1<=m<=200.1<=n< ...
- egg.js路由的优雅改造
引言 在使用express,koa, 或者是egg.js进行node server开发的过程中,我们的路由基本上都是定义在controller层的,框架对于 node 原生路由都会进行一层封装,一版都 ...
- Java入门:基础算法之产生随机数
本程序演示使用Random类的呢想tInt()方法产生随机数. /* Program: 随机数发生器 * Written by: 理工云课堂 * Input: None * Output: 0 到20 ...