[bzoj2038]莫队算法学习

解题关键:莫队最重要的是区间之间以$O(1)$的复杂度进行转化,由于电脑原因,后续补上公式推导。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<iostream>
 6 #include<cmath>
 7 using namespace std;
 8 typedef long long ll;
 9 ll n,m,ans;
10 struct node{
11     ll l,r,id;
12 }b[50002];
13 struct nd{
14     ll a,b;
15 }as[50002];
16 ll a[50002],pos[50002],s[50002];
17
18 bool cmp1(const node &a,const node &b){
19     return ((pos[a.l]==pos[b.l])&&(a.r<b.r))||(pos[a.l]<pos[b.l]);
20 }
21
22 void init(){
23     ll block=sqrt(n);
24     for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
25 }
26
27 void update(ll p,ll add){
28     /*ans-=s[a[p]]*s[a[p]];
29     s[a[p]]+=add;
30     ans+=s[a[p]]*s[a[p]];*/
31     ans+=2*add*s[a[p]]+(add==1?0:2);
32     s[a[p]]+=add;
33 }
34
35 void solve(){
36     for(int i=1,l=1,r=0;i<=m;i++){
37         for(;r<b[i].r;r++)  update(r+1,1);
38         for(;r>b[i].r;r--)  update(r, -1);
39         for(;l<b[i].l;l++)  update(l, -1);//这里注意搞清楚
40         for(;l>b[i].l;l--)  update(l-1,1);
41         if(b[i].l==b[i].r){
42             as[b[i].id].a=0,as[b[i].id].b=1;//题目要求
43             continue;
44         }
45         ll c=ans;
46         ll d=(b[i].r-b[i].l+1)*(b[i].r-b[i].l);
47         ll k=__gcd(c,d);
48         c/=k,d/=k;
49         as[b[i].id].a=c,as[b[i].id].b=d;
50     }
51 }
52 int main(){
53     cin>>n>>m;
54     for(int i=1;i<=n;i++) cin>>a[i];
55     for(int i=1;i<=m;i++){
56         cin>>b[i].l>>b[i].r;
57         b[i].id=i;
58     }
59     init();
60     sort(b+1,b+m+1,cmp1);
61     solve();
62     for(int i=1;i<=m;i++){
63         cout<<as[i].a<<"/"<<as[i].b<<"\n";
64     }
65 }
时间: 2024-10-12 15:29:18

[bzoj2038]莫队算法学习的相关文章

莫队算法学习笔记【BZOJ2038:小Z的袜子】【SPOJ3267:D-query】

很久以前傻乎乎地看来源奇怪的资料的时候被各种曼哈顿弄晕了. 然后现在学会的是分块方法.另新创一个分块方法. 让我们考虑这样一个区间询问问题…… 它有如下的性质: 0,n个数,Q个询问. 1,它没有修改操作,这意味着我们可以按我们喜欢的次序跟询问玩耍.实际上后面会讲到我们完全可以按任意次序玩耍. 2,如果我们知道区间询问 [L , R] 对应的值,我们可以轻易求出 [L±1 , R] 和 [L , R±1] 的值. (其实如果限制增加,比如只能求 [L+1 , R] 和 [L , R-1] 的值,

带修改的莫队算法学习小记

简介 莫涛大神创造出的离线询问算法的带修改版. 算法基础:需要掌握莫队算法,会打暴搜(暴力). 一个叫莫的双端队列. 只支持单点修改 操作方法 普通的不带修改的莫队算法要把每个询问带上两个关键字排序,现在待修改的莫队算法要带上三个关键字排序. 初始操作 fo(i,1,m) { scanf("%s%d%d",s,&k,&l); if (s[0]=='Q')a[++tot].l=k,a[tot].r=l,a[tot].x=num,a[tot].p=tot; else d[+

莫队算法学习小记

算法创始人 莫涛大神. 莫涛队长的算法,%%%%%%%%% 算法简介 算法前提 可以在O(1)的时间内把[l,r]的询问转移到[l-1,r],[l+1,r],[l,r-1],[l,r+1]的询问,而且不需要修改操作,那么就可以使用莫队算法([a,b]表示从a到b的区间,包含a和b) 算法核心 假如有一个询问[l,r]要转移到一个询问[l1,r1],那么需要的时间为O(|l1?l|+|r1?r|),在算法前提下,可以用这么多的时间暴力转移. 但是可以发现有时候有些点会被来回算很多次,这样大量浪费了

BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&amp;&amp;学习笔记】

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 9894  Solved: 4561[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两

[bzoj2038 [2009国家集训队]小Z的袜子(hose)] 莫队算法

题意:Q个询问,每个询问给定区间[L,R],求从里面任选两个数相同的概率. 思路:莫队算法.用一个cnt数组记录当前区间每种数的个数,区间变化为1时O(1)的维护cnt数组,并可以O(1)的得到当前区间中与当前数相同的数的个数. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7687  Solved: 3516[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只

BZOJ2038 [2009国家集训队]小Z的袜子(hose)(莫队算法)

神奇的莫队算法,用来解决可离线无修改的区间查询问题: 首先对原序列进行分块,√n块每块√n个: 然后对所有查询的区间[l,r]进行排序,首先按l所在的块序号升序排序,如果一样就按r升序排序: 最后就按顺序一个一个求出各个查询的结果:知道[l,r]的答案,并且在此基础上能在比较快地在O(x)得到相邻区间[l+1,r].[l-1,r].[l,r-1].[l,r+1]的答案,那样就能从[l,r]的基础上对lr加加减减得到任意一个区间[l',r']的答案. 看似暴力,但这样做的时间复杂度是O(x*n*√

bzoj2038 小Z的袜子(hose)——莫队算法

题目: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=

「知识学习&amp;日常训练」莫队算法(一)(Codeforce Round #340 Div.2 E)

题意 已知一个长度为\(n\)的整数数列\(a[1],a[2],-,a[n]\),给定查询参数\(l,r\),问\([l,r]\)内,有多少连续子段满足异或和等于\(k\). 也就是说,对于所有的\(x,y (l\le x\le y\le r)\),能够满足\(a[x]\oplus a[x+1]\oplus ...\oplus a[y]=k\)的\((x,y)\)有多少组. 分析 对于这种离线区间的查询问题(不涉及对区间的更改),我们可以使用莫队算法解决.这类问题是什么类型?对于序列上的区间询问