HYSBZ2038 小Z的袜子(莫队算法)
今天学了一下传说中的解决离线询问不修改的一种算法。题目的意思非常简单,就是询问在一个[L,R]区间里的取两个物品,然后这两个物品颜色相同的概率。其实就是对于每种颜色i,这个区间里对应的个数cnt[i],那么答案就应该是 sigma (cnt[i]*cnt[i-1]) / (R-L+1)*(R-L). 问题是要是每次询问我都遍历一遍的话必T无疑。这个时候莫队算法就给出了其中一种非常重要的离线处理方法,通过合适的安排询问的次序降低一定的复杂度。
举个例子,假如我询问的时候是询问[1,2],[1,3],[1,4],[1,5],[1,6]...[1,7],[2,7],显然我们每次计算这些答案都是O(1)的。但是假如询问的时候次序变一下
[2,7],[1,3],[1,7],[1,2]....这样子的话我们就会很蛋疼,所以通过合理的安排区间询问的顺序可以降低复杂度,而莫队算法就是这样做的。
首先假如我们已经知道了[L,R]的答案,如果我们可以O(1)的时间得出[L+1,R],[L-1,R],[L,R+1],[L,R-1]的话,那么下面这种算法就是可以实施的,我们通过对询问分块处理,假如区间长度为n,那么我们分成sqrt(n)块,然后对区间排序,排序的时候按照左端点属于那个块先排序,然后再按右端点的大小排序。排完序之后,我们就根据当前的[L,R]不断地去算下一个区间的[Li,Ri].其中就是根据L,Li和R,Ri的差值去变化求出对应的答案。
下面看下复杂度。我们总是从左到右处理一系列的询问,所以对于同一块里的询问如果有k个的话,那么由于左端点总是在同一个块里动,所以每次左端点动是O(sqrt(n)),而右端点递增,所以k次的总复杂度不会超过n,因此对于同一块的操作的总复杂度应该为 O(k*sqrt(n)+n)
假如询问的总数为m的话,那么由于最多有sqrt(n)块,所以总复杂度是 m*sqrt(n)+n*sqrt(n).
还有就是当由一个区间转换到相邻的另一个区间的时候,左端点移动不超过O(sqrt(n)),右端点移动不超过O(n),最多变动sqrt(n)次。所以转换区间的时候的复杂度是sqrt(n)*sqrt(n)+n*sqrt(n).
综上我们可以看出最后的复杂度应该是n^1.5.
这种神奇的分块处理原来还只是一种简约版。由上面可以看出,两次转移的复杂度取决于[L,R] [Li,Ri]的曼哈顿距离 abs(L-Li)+abs(R-Ri),所以如果能够合适安排这样的距离使得总的曼哈顿距离最小,那么还能再进一步优化,涉及到了曼哈顿最小生成树的概念,反正我是没看懂,今天学下这种分块的思想练练手~
#pragma warning (disable:4996)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std; #define maxn 55000
#define ll long long ll color[maxn];
ll cnt[maxn];
int n, m; int pos[maxn];
struct Query
{
int l, r,id;
bool operator < (const Query &b) const{
return pos[l] == pos[b.l] ? r < b.r : pos[l] < pos[b.l];
}
}q[maxn]; ll gcd(ll a, ll b){
return a&&b ? gcd(b, a%b) : a + b;
} ll resl[maxn], resr[maxn]; int main()
{
while (cin >> n >> m)
{
for (int i = 1; i <= n; i++){
scanf("%lld", color + i);
}
for (int i = 1; i <= m; i++){
scanf("%d%d", &q[i].l, &q[i].r);
q[i].id = i;
}
int bas = int(sqrt(n + .5));
for (int i = 1; i <= n; i++){
pos[i] = i / bas;
}
memset(cnt, 0, sizeof(cnt));
sort(q + 1, q + 1 + m);
int l = 1, r = 1; ll ans = 0;
cnt[color[1]] ++;
for (int i = 1; i <= m; i++){
if (r < q[i].r){
for (int k = r + 1; k <= q[i].r; k++){
ans -= cnt[color[k]] * (cnt[color[k]] - 1);
cnt[color[k]]++;
ans += cnt[color[k]] * (cnt[color[k]] - 1);
}
}
else if (r>q[i].r){
for (int k = r ; k >= (q[i].r+1); k--){
ans -= cnt[color[k]] * (cnt[color[k]] - 1);
cnt[color[k]]--;
ans += cnt[color[k]] * (cnt[color[k]] - 1);
}
}
if (l < q[i].l){
for (int k = l; k <= q[i].l-1; k++){
ans -= cnt[color[k]] * (cnt[color[k]] - 1);
cnt[color[k]]--;
ans += cnt[color[k]] * (cnt[color[k]] - 1);
}
}
else if (l>q[i].l){
for (int k = l - 1; k >= q[i].l; k--){
ans -= cnt[color[k]] * (cnt[color[k]] - 1);
cnt[color[k]]++;
ans += cnt[color[k]] * (cnt[color[k]] - 1);
}
}
l = q[i].l; r = q[i].r;
ll len = q[i].r - q[i].l+1;
ll tot = len*(len - 1);
ll g = gcd(ans, tot);
resl[q[i].id] = ans / g; resr[q[i].id] = tot / g;
}
for (int i = 1; i <= m; i++){
printf("%lld/%lld\n", resl[i], resr[i]);
}
}
return 0;
}
HYSBZ2038 小Z的袜子(莫队算法)的更多相关文章
- 【国家集训队2010】小Z的袜子[莫队算法]
[莫队算法][国家集训队2010]小Z的袜子 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程, ...
- bzoj 2308 小Z的袜子(莫队算法)
小Z的袜子 [题目链接]小Z的袜子 [题目类型]莫队算法 &题解: 莫队算法第一题吧,建议先看这个理解算法,之后在参考这个就可以写出简洁的代码 我的比第2个少了一次sort,他的跑了1600m ...
- [日常摸鱼]bzoj2038[2009国家集训队]小Z的袜子-莫队算法
今天来学了下莫队-这题应该就是这个算法的出处了 一篇别人的blog:https://www.cnblogs.com/Paul-Guderian/p/6933799.html 题意:一个序列,$m$次询 ...
- bzoj 2038 小Z的袜子 莫队算法
题意 给你一个长度序列,有多组询问,每次询问(l,r)任选两个数相同的概率.n <= 50000,数小于等于n. 莫队算法裸题. 莫队算法:将序列分为根号n段,将询问排序,以L所在的块为第一关键 ...
- BZOJ 2038 小z的袜子 & 莫队算法(不就是个暴力么..)
题意: 给一段序列,询问一个区间,求出区间中.....woc! 贴原题! 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过 ...
- Luogu 1494 - 小Z的袜子 - [莫队算法模板题][分块]
题目链接:https://www.luogu.org/problemnew/show/P1494 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天 ...
- 小Z的袜子 & 莫队
莫队学习 & 小Z的袜子 引入 莫队 由莫涛巨佬提出,是一种离线算法 运用广泛 可以解决广大的离线区间询问题 莫队的历史 早在mt巨佬提出莫队之前 类似莫队的算法和莫队的思想已在Codefor ...
- BZOJ 2038 [2009国家集训队]小Z的袜子 莫队
2038: [2009国家集训队]小Z的袜子(hose) 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Descriptionw ...
- BZOJ2038 [2009国家集训队]小Z的袜子 莫队+分块
作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从 ...
- P1494 [国家集训队]小Z的袜子/莫队学习笔记(误
P1494 [国家集训队]小Z的袜子 题目描述 作为一个生活散漫的人,小\(Z\)每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小\(Z\)再也无法忍受这恼人的找袜子过程,于是他 ...
随机推荐
- SQL基础篇----select语句与排序问题
一.检索--输出所有的列 SELECT * FROM my_friends WHEREfirst_name = 'cake'; 知识点1 * 代表选择出所有的行-----(什么行呢?)就是first_ ...
- jQuery对象与DOM对象
jQuery对象与DOM对象是不一样的 可能一时半会分不清楚哪些是jQuery对象,哪些是DOM对象,下面重点介绍一下jQuery对象,以及两者相互间的转换. 通过一个简单的例子,简单区分下jQuer ...
- umask设置导致的weblogic中的应用上传的文件没有权限打开
去年,在公司的某一weblogic上部署的web应用上传文件后却没有读的权限.因为weblogic在Linux上部署,上传文件是mount到了一台安装了NFS的Windows Server上. 当时本 ...
- JavaScript高级程序设计之原型对象
构造函数.原型对象.构造器是一体的关系,同时产生: 实例中的隐藏属性__proto__指向原型对象: 原型对象是这四种关系的纽带. 原型对象是动态的,不论在何处变化,实例中可以立即体现出来. var ...
- linux命令行下使用R语言绘图
系统:centos 6.4 64bit 环境安装参考:http://hi.baidu.com/solohac/item/4a18e78f1bef9b5825ebd99c 在R语言中可以使用png()等 ...
- IOS开发的国际化
一 app中内容的国际化 1 添加简体中文支持(默认只有英文) 在xcode的PROJECT->Info->Localizations下添加简体中文的支持. 2新建St ...
- ext4.1动态生成多个checkboxgroup(或者radiogroup),并且有toolbar操作、
转载自:http://blog.csdn.net/zhengyuechuan/article/details/9327291 前台controller代码: Ext.define('zyc.contr ...
- easyui中jquery重复引用问题(tab内存泄露问题)
今天认真测试了下easyui的一些兼容性问题,发现在ie9 ie10 首次加载的时候,会出现如下bug.如图所示: 认真看了下,我估计是脚本重复引用的问题,我用的iframe框架的模式.登陆系统后,桌 ...
- 通过 CALayer 修改 UIImageView 的界面属性
界面属性的修改是每一个开发者必须知道的,为什么我就记不住呢, shit, 又耽误了时间,为了防止再找不到,特把一些常用的 CALayer属性记在这里,顺便分享 1.设置阴影 1 imageView.l ...
- Ubuntu14.04搭建LAMP环境
安装Apache2 sudo apt-get install apache2 ...