bzoj 2038: [2009国家集训队]小Z的袜子(hose) 莫队算法
2016-08-16 21:10
351 查看
题意:有n只袜子,每只袜子有自己的颜色,有m个询问l,r表示l到r这个区间内拿到两只颜色相同的袜子的概率是多少。
分析:第一次打莫队算法
莫队算法的思路是,对询问进行排序,以左端点所在块为第一关键字,右端点为第二关键字,进行排序。然后维护[l,r]的答案,并不断调整l和r。
复杂度是怎么样的呢?
1、左端点所在块确定时,右端点单调,所以右端点移动造成的复杂度是o(n)的,总共n^0.5块,总复杂度o(n^1.5)
2、左端点所在块进行变动时,右端点最多移动o(n),总共n^0.5块,变动次数也就是n^0.5,总复杂度o(n^1.5)
3、块内左端点每次最多变动n^0.5,最多变动n^0.5次,总共n^0.5块,总复杂度o(n^1.5)
这题注意要开long long
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 50005
#define ll long long
using namespace std;
int n,m,block,pos
,a
,t
;
ll ans;
struct data{int l,r,id;ll a,b;}q
;
void init()
{
scanf("%d%d",&n,&m);
block=int(sqrt(n));
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pos[i]=(i-1)/block+1;
}
for (int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
}
bool cmp(data a,data b)
{
if (pos[a.l]==pos[b.l]) return a.r<b.r;
return pos[a.l]<pos[b.l];
}
void updata(int x,int y)
{
if (y==1)
{
ans+=t[a[x]];
t[a[x]]++;
}else
{
ans-=t[a[x]]-1;
t[a[x]]--;
}
}
ll gcd(ll x,ll y)
{
if (x%y==0) return y;
return gcd(y,x%y);
}
void query()
{
updata(1,1);
for (int i=1,l=1,r=1;i<=m;i++)
{
for (;r<q[i].r;r++)
updata(r+1,1);
for (;r>q[i].r;r--)
updata(r,-1);
for (;l<q[i].l;l++)
updata(l,-1);
for (;l>q[i].l;l--)
updata(l-1,1);
if (!ans)
{
q[i].a=0;q[i].b=1;
continue;
}
q[i].a=ans;q[i].b=(ll)(q[i].r-q[i].l+1)*(q[i].r-q[i].l)/2;
ll k=gcd(q[i].b,q[i].a);
q[i].a/=k;q[i].b/=k;
}
}
bool cmp1(data a,data b)
{
return a.id<b.id;
}
int main()
{
init();
sort(q+1,q+m+1,cmp);
query();
sort(q+1,q+m+1,cmp1);
for (int i=1;i<=m;i++)
printf("%lld/%lld\n",q[i].a,q[i].b);
return 0;
}
分析:第一次打莫队算法
莫队算法的思路是,对询问进行排序,以左端点所在块为第一关键字,右端点为第二关键字,进行排序。然后维护[l,r]的答案,并不断调整l和r。
复杂度是怎么样的呢?
1、左端点所在块确定时,右端点单调,所以右端点移动造成的复杂度是o(n)的,总共n^0.5块,总复杂度o(n^1.5)
2、左端点所在块进行变动时,右端点最多移动o(n),总共n^0.5块,变动次数也就是n^0.5,总复杂度o(n^1.5)
3、块内左端点每次最多变动n^0.5,最多变动n^0.5次,总共n^0.5块,总复杂度o(n^1.5)
这题注意要开long long
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 50005
#define ll long long
using namespace std;
int n,m,block,pos
,a
,t
;
ll ans;
struct data{int l,r,id;ll a,b;}q
;
void init()
{
scanf("%d%d",&n,&m);
block=int(sqrt(n));
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pos[i]=(i-1)/block+1;
}
for (int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
}
bool cmp(data a,data b)
{
if (pos[a.l]==pos[b.l]) return a.r<b.r;
return pos[a.l]<pos[b.l];
}
void updata(int x,int y)
{
if (y==1)
{
ans+=t[a[x]];
t[a[x]]++;
}else
{
ans-=t[a[x]]-1;
t[a[x]]--;
}
}
ll gcd(ll x,ll y)
{
if (x%y==0) return y;
return gcd(y,x%y);
}
void query()
{
updata(1,1);
for (int i=1,l=1,r=1;i<=m;i++)
{
for (;r<q[i].r;r++)
updata(r+1,1);
for (;r>q[i].r;r--)
updata(r,-1);
for (;l<q[i].l;l++)
updata(l,-1);
for (;l>q[i].l;l--)
updata(l-1,1);
if (!ans)
{
q[i].a=0;q[i].b=1;
continue;
}
q[i].a=ans;q[i].b=(ll)(q[i].r-q[i].l+1)*(q[i].r-q[i].l)/2;
ll k=gcd(q[i].b,q[i].a);
q[i].a/=k;q[i].b/=k;
}
}
bool cmp1(data a,data b)
{
return a.id<b.id;
}
int main()
{
init();
sort(q+1,q+m+1,cmp);
query();
sort(q+1,q+m+1,cmp1);
for (int i=1;i<=m;i++)
printf("%lld/%lld\n",q[i].a,q[i].b);
return 0;
}
相关文章推荐
- BZOJ 2038 [2009国家集训队]小Z的袜子(hose) (莫队算法)
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) 【莫队算法】
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)(莫队算法)
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)|分块|莫队算法
- bzoj 2038: [2009国家集训队]小Z的袜子(hose)(莫队算法)
- [BZOJ]2038: [2009国家集训队]小Z的袜子(hose) 莫队算法
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)&&莫队算法
- bzoj 2038: [2009国家集训队]小Z的袜子(hose) 【莫队算法】
- bzoj 2038 [2009国家集训队]小Z的袜子(hose)(莫队算法)
- BZOJ 2038([2009国家集训队]小Z的袜子(hose)-莫队算法序列)
- bzoj 2038: [2009国家集训队]小Z的袜子(hose) 莫队算法
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&&学习笔记】
- BZOJ2038 [2009国家集训队]小Z的袜子(hose)(莫队算法)
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) 莫队算法
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)(莫队算法)
- bzoj 2038: [2009国家集训队]小Z的袜子(hose)(莫队算法)
- bzoj 2038: [2009国家集训队]小Z的袜子(hose) (莫队算法)
- BZOJ 2038 2009国家集训队 小Z的袜子(hose) 莫队算法
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) (莫队算法)