清橙A1206.小Z的袜子 && CF 86D(莫队两题)
清橙A1206.小Z的袜子 && CF 86D(莫队两题)
在网上看了一些别人写的关于莫队算法的介绍,我认为,莫队与其说是一种算法,不如说是一种思想,他通过先分块再排序来优化离线查询问题。
应用范围:一般问题是让你回答多个连续区间上的问题,如果你知道了区间【l,r】的答案、你就可以在O(1)或O(logn)时间内知道【l+1,r】、【l,r+1】、【l-1,r】、【l,r-1】区间的答案,那么你就可以应用莫队算法。
实现方法:数组长度为n,查询个数为m。先读入所有查询,然后把查询【l,r】按l/sqrt(m)递增的的顺序排序,如果相同再按r递增的顺序排序,然后维护当前区间的查询值,再按排好的序从前到后暴力跑一遍就OK了。
原理阐述:到这里很多人可能要问一个问题,为什么要分sqrt(m)块?这个问题也困扰了我好久,不过经过一番冥想,我终于找到了答案:假设我们要把查询分成x块,那么每块中 r 的移动量最大为n、总的移动量为n*x,每块中 l 的移动量最大为n/t、总的移动量为m*n/x,整个查询的复杂度为(n*x+n*m/x),根据数学知识我们可以知道,在n*x=n*m/x的时候总的复杂度是最小的,这时x=sqrt(m),复杂度为O(2*n*sqrt(m)),这样莫队按sqrt(m)分块的合理性就得到了证明。
入门题1:青橙A1206.小Z的袜子
长度为n的数组,有m个询问,每个询问你需要回答:在该区间内任意抽两个数字且两个数字的数值相同的概率是多大,答案需要时最简分数的形式。
思路:对于区间【l,r】,其不同数值的数的个数分别为a、b、.....、c,那么上述的概率就是(a^a+b^b+...+c^c-(r-l+1))/(r-l)*(r-l+1)。(不要问我是咋推出来的)。
解法:维护当前区间【l,r】中数值为v的数的个数cnt【v】,如果该区间答案为temp,那么对于区间【l,r+1】,你可以在O(1)时间内求出新的temp,那么久可以运用莫队来搞定了。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std; const int maxn=;
typedef long long LL;
int n,m; LL gcd(LL a,LL b){
if(b==) return a;
return gcd(b,a%b);
} struct ANS{
LL a,b;
void simple(){
LL kk=gcd(a,b);
a/=kk;
b/=kk;
}
}ans[maxn]; struct node{
int l,r,id;
}q[maxn]; int cmp(const node& a,const node& b){
if(a.l/(int)sqrt(m)!=b.l/(int)sqrt(m)) return a.l/(int)sqrt(m)<b.l/(int)sqrt(m);
return a.r<b.r;
} int c[maxn];
int cnt[maxn]; void solve(){
cnt[c[]]++;
LL temp=;
int l=;
int r=;
for(int i=;i<=m;i++){
//cout<<l<<" "<<r<<endl;
while(l<q[i].l){
temp=temp-cnt[c[l]]*cnt[c[l]];
cnt[c[l]]--;
temp=temp+cnt[c[l]]*cnt[c[l]];
l++;
}
while(l>q[i].l){
l--;
temp=temp-cnt[c[l]]*cnt[c[l]];
cnt[c[l]]++;
temp=temp+cnt[c[l]]*cnt[c[l]];
}
while(r<q[i].r){
r++;
temp=temp-cnt[c[r]]*cnt[c[r]];
cnt[c[r]]++;
temp=temp+cnt[c[r]]*cnt[c[r]];
}
while(r>q[i].r){
temp=temp-cnt[c[r]]*cnt[c[r]];
cnt[c[r]]--;
temp=temp+cnt[c[r]]*cnt[c[r]];
r--;
}
//cout<<q[i].id<<endl;
ans[q[i].id].a=temp-(r-l+);
ans[q[i].id].b=(LL)(r-l+)*(r-l);
ans[q[i].id].simple();
}
} int main (){
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=;i<=n;i++){
scanf("%d",&c[i]);
}
for(int i=;i<=m;i++){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+,q+m+,cmp);
memset(cnt,,sizeof(cnt));
solve();
for(int i=;i<=m;i++)
cout<<ans[i].a<<"/"<<ans[i].b<<endl;
}
return ;
}
入门题2: CF 86D Powerful array
http://codeforces.com/problemset/problem/86/D
题意:给你一个长度为n的数组,m个询问,每个询问需要你回答对于给出的区间【l,r】,sigma(cnt[v]*cnt[v]*v),其中v是【l,r】内的数字,cnt[v]是【l,r】内v的个数。
解法:区间的范围每移动一次,就可以在O(1)时间内完成更新,故可以使用莫队算法(具体实现详见代码)
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std; typedef long long LL;
const int maxn=;
const int maxa=1e6; int n,t; struct node{
int l,r,id;
}q[maxn]; int cmp(const node& a,const node& b){
if(a.l/(int)sqrt(t)!=b.l/(int)sqrt(t)) return a.l/(int)sqrt(t)<b.l/(int)sqrt(t);
return a.r<b.r;
} int cnt[maxa+];
int a[maxn];
LL ans[maxn]; LL temp;
void update(int cur,int change){
temp-=(LL)cnt[a[cur]]*cnt[a[cur]]*a[cur];
cnt[a[cur]]+=change;
temp+=(LL)cnt[a[cur]]*cnt[a[cur]]*a[cur];
} void solve(){
temp=a[];
cnt[a[]]++;
int l=;
int r=;
for(int i=;i<=t;i++){
while(l<q[i].l){
update(l,-);
l++;
}
while(l>q[i].l){
l--;
update(l,);
}
while(r>q[i].r){
update(r,-);
r--;
}
while(r<q[i].r){
r++;
update(r,);
}
ans[q[i].id]=temp;
}
} int main (){
while(scanf("%d%d",&n,&t)!=EOF){
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
for(int i=;i<=t;i++){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+,q+t+,cmp);
memset(cnt,,sizeof(cnt));
solve();
for(int i=;i<=t;i++)
cout<<ans[i]<<endl;
}
return ;
}
清橙A1206.小Z的袜子 && CF 86D(莫队两题)的更多相关文章
- 清橙 A1206 小Z的袜子(莫队算法)
A1206. 小Z的袜子 时间限制:1.0s 内存限制:512.0MB 总提交次数:1357 AC次数:406 平均分:46.75 将本题分享到: 查看未格式化的试题 ...
- BZOJ_2038_[2009国家集训队]小Z的袜子(hose)_莫队
BZOJ_2038_[2009国家集训队]小Z的袜子(hose)_莫队 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无 ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&&学习笔记】
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 9894 Solved: 4561[Subm ...
- 2038: [2009国家集训队]小Z的袜子(hose) (莫队算法)
题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=2038 专题练习: http://acm.hust.edu.cn/vjudge/conte ...
- BZOJ2038 2009国家集训队 小Z的袜子(hose) 【莫队】
BZOJ2038 2009国家集训队 小Z的袜子(hose) Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼 ...
- bzoj 2038 小Z的袜子(hose)(莫队算法)
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 11542 Solved: 5166[Sub ...
- [bzoj2038][2009国家集训队]小Z的袜子(hose)_莫队
小Z的袜子 hose 2009-国家集训队 bzoj-2038 题目大意:给定一个n个袜子的序列,每个袜子有一个颜色.m次询问:每次询问一段区间中每种颜色袜子个数的平方和. 注释:$1\le n,m\ ...
- 【BZOJ2038】【2009国家集训队】小Z的袜子(hose) 分块+莫队
Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜 ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) 【莫队算法】
Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜 ...
随机推荐
- 忘记Oracle密码
1./as sysdba 2.然后你忘记密码的用户名例如Scott alter user scott identified by root 3.exit 4.sqlplus 重新登录
- Java_Web三大框架之Hibernate增删改查
下面介绍一下Hibernate的增删改查. 第一步:编写用户实体类以及User.hbm.xml映射 package com.msl.entity; public class User { privat ...
- HashMap中capacity、loadFactor、threshold、size等概念的解释
约定 约定前面的数组结构的每一个格格称为桶 约定桶后面存放的每一个数据称为bin bin这个术语来自于JDK 1.8的HashMap注释. size size表示HashMap中存放KV的数量(为链表 ...
- 转录组入门(3):了解fastq测序数据
sra文件转换为fastq格式 fastq-dump -h --split-3 也就是说如果SRA文件中只有一个文件,那么这个参数就会被忽略.如果原文件中有两个文件,那么它就会把成对的文件按*_1.f ...
- 8 switch case
当一个case成立,从这个case向后穿透所有case,即使后面的case条件不成立 包括default,直到程序结束或者遇到break程序才结束. 1.case是常量,且不能重复 2.表达式可以是b ...
- 彩色MT9V034摄像头 Bayer转rgb FPGA实现
1 图像bayer格式介绍 bayer格式是伊士曼·柯达公司科学家Bryce Bayer发明的,Bryce Bayer所发明的拜耳阵列被广泛运用数字图像.Bayer格式是相机内部的原始数据, 一般后缀 ...
- 【Apache Kafka】一、Kafka简介及其基本原理
对于大数据,我们要考虑的问题有很多,首先海量数据如何收集(如Flume),然后对于收集到的数据如何存储(典型的分布式文件系统HDFS.分布式数据库HBase.NoSQL数据库Redis),其次存储 ...
- 使用 lua 编写 wireshark 协议解析插件
一.平台 操作系统:windows 7 wireshark:1.10.3 lua:5.1 二.准备 lua 语言基本语法,特别是关于表操作和循环 wireshark 文档,包括用户使用文档和开发者文档 ...
- nlogn求LIS(树状数组)
之前一直是用二分 但是因为比较难理解,写的时候也容易忘记怎么写. 今天比赛讲评的时候讲了一种用树状数组求LIS的方法 (1)好理解,自然也好写(但代码量比二分的大) (2)扩展性强.这个解法顺带求出以 ...
- PAT 1118 Birds in Forest
Some scientists took pictures of thousands of birds in a forest. Assume that all the birds appear in ...