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*√n) !因为:

  • l是按其所在块序号排列,同一块里面一次最多√n次++l或--l到达目标;一块最多大概√n次加加减减;总共√n块;所以l改变的次数顶多也就√n*√n*√n。
  • r在同一块是升序的,所以同一块最多n次++r;下一块时r假设在上一块到达最远,那最多n次--r回到目标;总共√n块;所以r改变次数顶多也就(n+n)*√n。
  • 而每次加加减减转移新答案的代价是x,所以时间复杂度是O(x*n*√n) !

这一题,设每个区间[l,r]各个颜色的袜子数分别为$a,b,c,d,\dots$,每个区间[l,r]的答案就是$(C_a^2+C_b^2+C_c^2+C_d^2+\cdots)/C_{r-l+1}^2$,展开化简得:

$$(a^2+b^2+c^2+d^2+\cdots-a-b-c-d-\cdots)/((r-l+1)*(r-l+1-1))$$

$$(a^2+b^2+c^2+d^2+\cdots-(r-l+1))/((r-l+1)*(r-l))$$

其中$(a^2+b^2+c^2+d^2+\cdots)$便可作为莫队算法处理的区间答案,开个数组记录abcd...的个数可以在O(1)转移到相邻区间。

另外特判区间l=r的情况。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 #define MAXN 55555
 7
 8 int block;
 9 struct Query{
10     int i,l,r;
11     bool operator<(const Query &q)const{
12         if(l/block==q.l/block) return r<q.r;
13         return l/block<q.l/block;
14     }
15 }query[MAXN];
16
17 long long gcd(long long a,long long b){
18     if(b==0) return a;
19     return gcd(b,a%b);
20 }
21
22 int seq[MAXN];
23 long long cnt[MAXN],ansx[MAXN],ansy[MAXN];
24 void insert(long long &res,int a){
25     res-=cnt[a]*cnt[a];
26     ++cnt[a];
27     res+=cnt[a]*cnt[a];
28 }
29 void remove(long long &res,int a){
30     res-=cnt[a]*cnt[a];
31     --cnt[a];
32     res+=cnt[a]*cnt[a];
33 }
34 int main(){
35     int n,m;
36     scanf("%d%d",&n,&m);
37     block=sqrt(n);
38     for(int i=1; i<=n; ++i) scanf("%d",seq+i);
39     for(int i=0; i<m; ++i){
40         query[i].i=i;
41         scanf("%d%d",&query[i].l,&query[i].r);
42     }
43     sort(query,query+m);
44     int l=1,r=1;
45     ++cnt[seq[1]];
46     long long res=1;
47     for(int i=0; i<m; ++i){
48         if(query[i].l==query[i].r){
49             ansx[query[i].i]=0; ansy[query[i].i]=1;
50             continue;
51         }
52         while(l<query[i].l){
53             remove(res,seq[l]);
54             ++l;
55         }
56         while(l>query[i].l){
57             --l;
58             insert(res,seq[l]);
59         }
60         while(r<query[i].r){
61             ++r;
62             insert(res,seq[r]);
63         }
64         while(r>query[i].r){
65             remove(res,seq[r]);
66             --r;
67         }
68         long long a=res-(query[i].r-query[i].l+1),b=(query[i].r-query[i].l+1LL)*(query[i].r-query[i].l),c=gcd(b,a);
69         ansx[query[i].i]=a/c; ansy[query[i].i]=b/c;
70     }
71     for(int i=0; i<m; ++i) printf("%lld/%lld\n",ansx[i],ansy[i]);
72     return 0;
73 }
时间: 2024-10-30 14:25:34

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

[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: 10239  Solved: 4659[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命--具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两

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) [莫队]

Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬.你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子.当然,小Z希望这个概率尽量高,所以他可能会询问多个(L,R)以方便自己选择

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

题目链接:点击打开链接 先把询问处理成曼哈顿最小生成树. 然后在树上暴力跑即可. 能使用莫队的情况应该是对于询问[l,r] -> [l', r'] 花费必须是 abs(l-l') + abs(r-r') #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h

BZOJ 2038: [2009国家集训队]小Z的袜子(hose) ( 莫队 )

莫队..先按sqrt(n)分块, 然后按块的顺序对询问排序, 同块就按右端点排序. 然后就按排序后的顺序暴力求解即可. 时间复杂度O(n1.5) ------------------------------------------------------------------------------ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 50009; int N,

2038: [2009国家集训队]小Z的袜子(hose)+莫队入门

题目链接:2038: [2009国家集训队]小Z的袜子(hose) 题目: Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬.你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子

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

bzoj2038-[2009国家集训队]-小z的袜子(hose) F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  Manacher Logout 捐赠本站 Notice:省选季快乐&另求历年World Final数据,谢谢&OJ试题突破3000大关! 2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MB Submit: 

bzoj 2038: [2009国家集训队]小Z的袜子(hose) (莫队)

Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬.你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子.当然,小Z希望这个概率尽量高,所以他可能会询问多个(L,R)以方便自己选择