您的位置:首页 > 其它

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

2017-10-30 18:42 295 查看

题目大意:

莫队算法经典例题,把多次区间查询离线排序,生成一个对于某种递推的计算方法来说,比较优的询问序列,然后用上一个查询的答案生成下一次查询的答案。

代码:

#include<bits/stdc++.h>
using namespace std;
#define maxn 500050
int n,a[maxn],pos[maxn],m;
long long int num[maxn],ans=0;
struct mo
{
int l;int r;int id;long long int ans;
}q[maxn];

bool mo_cmp(mo a,mo b)
{
return pos[a.l]==pos[b.l] ? a.r<b.r : a.l<b.l ;
}
bool id_cmp(mo a,mo b)
{
return a.id < b.id ;
}
int main()
{
scanf("%d%d",&n,&m);
memset(num,0,sizeof(num));
int k=sqrt(n);
for(int i=0;i<=n;i++)pos[i]=i/k;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=0;i<m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i+1;
}
sort(q,q+m,mo_cmp);

for(int i=q[0].l ; i<=q[0].r ; i++ )
{
//ans+=num[a[i]];
ans-=((num[a[i]]*num[a[i]])-num[a[i]]);
num[a[i]]++;
//ans-=num[a[i]];
ans+=((num[a[i]]*num[a[i]])-num[a[i]]);
}
q[0].ans=ans;
int nowl=q[0].l , nowr=q[0].r;
//cout<<nowl<<" "<<nowr<<" "<<ans<<endl;
for(int i=1;i<m;i++)
{
//cout<<i<<endl;
while(nowl<q[i].l)
{
ans-=( (num[a[nowl]]*num[a[nowl]]) - num[a[nowl]] );
num[a[nowl]]--;
ans+=( (num[a[nowl]]*num[a[nowl]]) - num[a[nowl]] );
nowl++;
}
while(nowl>q[i].l)
{
nowl--;
ans-=( (num[a[nowl]]*num[a[nowl]]) - num[a[nowl]] );
num[a[nowl]]++;
ans+=( (num[a[nowl]]*num[a[nowl]]) - num[a[nowl]] );
}
while(nowr<q[i].r)
{
nowr++;
ans-=( (num[a[nowr]]*num[a[nowr]]) - num[a[nowr]] );
num[a[nowr]]++;
ans+=( (num[a[nowr]]*num[a[nowr]]) - num[a[nowr]] );

}
while(nowr>q[i].r)
{
ans-=( (num[a[nowr]]*num[a[nowr]]) - num[a[nowr]] );
num[a[nowr]]--;
ans+=( (num[a[nowr]]*num[a[nowr]]) - num[a[nowr]] );
nowr--;
}
q[i].ans=ans;
//cout<<i<<" "<<nowl<<" "<<nowr<<endl;
}

sort(q,q+m,id_cmp);
for(int i=0;i<m;i++)
{
long long int b,p;
b=q[i].ans;
p=(long long int )(q[i].r-q[i].l+1)*(q[i].r-q[i].l);
long long int g=__gcd( b , p );
//cout<<"sda";
if(g!=0&&b!=0&&q[i].l!=q[i].r)printf("%lld/%lld\n",b/g,p/g);
else printf("0/1\n");
//printf("%lld%lld",q[i].ans,g);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  莫队算法 acm 算法