BZOJ 2038 小z的袜子 & 莫队算法(不就是个暴力么..)

题意:

  给一段序列,询问一个区间,求出区间中.....woc! 贴原题!

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

sol:

  莫队大法好,莫队就是换一个方法打暴力,有一个非常6的论文,极为清楚易懂...(先挖个坑,找不到....)

  那么就直接上代码了...(第一发忘开ll....已经好几次这样了....

CODE:

  

/*==========================================================================
# Last modified: 2016-02-27 16:55
# Filename: 2038.cpp
# Description:
==========================================================================*/
#define me AcrossTheSky
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> 

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector> 

#define lowbit(x) (x)&(-x)
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)
#define ls(a,b) (((a)+(b)) << 1)
#define rs(a,b) (((a)+(b)) >> 1)
#define getlc(a) ch[(a)][0]
#define getrc(a) ch[(a)][1] 

#define maxn 100000
#define maxm 100000
#define pi 3.1415926535898
#define _e 2.718281828459
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 

template<class T> inline
void read(T& num) {
    bool start=false,neg=false;
    char c;
    num=0;
    while((c=getchar())!=EOF) {
        if(c==‘-‘) start=neg=true;
        else if(c>=‘0‘ && c<=‘9‘) {
            start=true;
            num=num*10+c-‘0‘;
        } else if(start) break;
    }
    if(neg) num=-num;
}
/*==================split line==================*/
int L,R;
struct Query{
	int l,r,id,op;
}q[maxm];
struct Answer{
	ll x,tot;
}ans[maxm];
bool cmp(const Query &x,const Query &y){
	if(x.op==y.op) return x.r<y.r;
	 else return x.op<y.op;
}
ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b);}
ll a[maxn],cnt[maxn];
ll tmp=0;

void add(int i){ tmp+=cnt[a[i]]; cnt[a[i]]++;}
void remove(int i){cnt[a[i]]--;tmp-=cnt[a[i]];}
void solve(int l,int r,int id){
	while (l>L) {remove(L); L++;}
	while (l<L) {L--; add(L);}
	while (r<R) { remove(R); R--;}
	while (r>R) { R++; add(R);}

	ans[id].x=tmp;
//	FORP(i,l,r) ans[id].x+=(cnt[i]*(cnt[i-1])/2);
}
int main(){
	int n,m; read(n); read(m);
	int sz=trunc(sqrt(n));//num=n/sz+n%sz?0:1;
	FORP(i,1,n)	read(a[i]);
	FORP(i,1,m){
		read(q[i].l); read(q[i].r); q[i].id=i;
		q[i].op=q[i].l/sz+(q[i].l%sz?1:0);
	}
	sort(q+1,q+1+m,cmp);
	tmp=0,L=q[1].l,R=q[1].r;
	ll num=R-L+1;
	FORP(i,L,R) add(i);
	ans[q[1].id].x=tmp; ans[q[1].id].tot=num*(num-1)/2;
	FORP(i,2,m){
		num=q[i].r-q[i].l+1 ;
		//if (i==1) L=q[i].l,R=q[i].r;
		ans[q[i].id].tot=num*(num-1)/2;
		solve(q[i].l,q[i].r,q[i].id);
	}
	FORP(i,1,m){
		if (ans[i].x==0) {printf("0/1\n"); continue;}
		ll t=gcd(ans[i].x,ans[i].tot);
		printf("%lld/%lld\n",ans[i].x/t,ans[i].tot/t);
	}
}
时间: 2024-10-12 08:23:28

BZOJ 2038 小z的袜子 & 莫队算法(不就是个暴力么..)的相关文章

BZOJ 2038 小Z的袜子(莫队算法)

莫队算法如果我们已知[l,r]的答案,能在O(1)时间得到[l+1,r]的答案以及[l,r-1]的答案,即可使用莫队算法.时间复杂度为O(n^1.5).如果只能在logn的时间移动区间,则时间复杂度是O(n^1.5*log n).其实就是找一个数据结构支持插入.删除时维护当前答案. 这道题的话我们很容易用数组来实现,做到O(1)的从[l,r]转移到[l,r+1]与[l+1,r]. 那么莫队算法怎么做呢?以下都是在转移为O(1)的基础下讨论的时间复杂度.另外由于n与m同阶,就统一写n.如果已知[l

bzoj 2038 小z的袜子 莫队例题

莫队,利用可以快速地通过一个问题的答案得到另一问题的答案这一特性,合理地组织问题的求解顺序,将已解决的问题帮助解决当前问题,来优化时间复杂度. 典型用法:处理静态(无修改)离线区间查询问题. 线段树也是处理区间问题的一个有力工具,它和莫队算法各有特点: 线段树可以支持修改,并且单次操作时间复杂度一般为O(log),支持在线,但是要求可以进行快速的区间合并操作,两个区间如不能快速合并(f(n)*O(log)>O(n)),则用线段树就没有什么实际价值了(暴力都比它块) 莫队算法可以解决某些线段树不能

清橙A1206 小Z的袜子(莫队算法)

A1206. 小Z的袜子 时间限制:1.0s   内存限制:512.0MB 总提交次数:744   AC次数:210   平均分:44.44 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2010中国国家集训队命题答辩 问题描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命-- 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是

BZOJ 2038 2009国家集训队 小Z的袜子 莫队算法

题目大意:给出一些袜子的排列顺序,每次问一段区间中有多少相同颜色的袜子对. 思路:莫队算法真是一个神奇的算法.首先,暴力枚举是O(n^2)的时间复杂度,这肯定是不行的.假如区间是保证不重合的,那么就可以将总的时间转移的复杂度降到O(n).很遗憾,题目中没有这个保证.于是乎,神秘的莫队就发明了一种神奇的算法. 对于每一个询问,我们将它看成一个平面上的点(x1,y1),同样的也就会有其他的点分布在平面中.假如还有一个点(x2,y2),那么我们从第一个区间转移到第二个区间需要改变的元素总数为|x1 -

Luogu 1494 - 小Z的袜子 - [莫队算法模板题][分块]

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

Luogu 1494 - 小Z的袜子 - [莫队算法模板题]

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

bzoj 2038 小Z的袜子(hose)(莫队算法)

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

BZOJ 2038 小Z的袜子(hose) (莫队离线)

题目地址:BZOJ 2038 裸的莫队算法. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> #includ

bzoj 2038 小Z的袜子

好久没写题解了=_= ,整个暑假就没写过,还是决定写写吧,所以挑了这道大水题. 这是标准的莫队算法的问题,但由于可能数据水还是别的什么原因,不用曼哈顿最小生成树也可以过.具体就是按询问区间的左端点分块, 块内按右端点排序,然后暴力…… 真的是暴力,太暴力了,直到AC以后我才相信这么暴力真的可以在O(N^1.5)的时间复杂度内过掉. 块内具体就是右端点递增,左端点由于在块内并不是有序的,所以左端点就会晃来晃去,真是太暴力了…… 上代码: #include <cstdio> #include &l