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

来源:互联网 发布:双硬盘安装ubuntu 编辑:程序博客网 时间:2024/06/10 22:25





http://www.lydsy.com/JudgeOnline/problem.php?id=2038






分析:

推荐一篇莫队算法讲解的博客:点击打开链接






AC代码:

#include <iostream>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>#include <vector>#include <stack>#include <queue>#include <map>#include <set>#include<list>#include <bitset>#include <climits>#include <algorithm>#define mset(a,n) memset(a,n,sizeof(a))#define FIN freopen("input.txt","r",stdin)#define FOUT    freopen("output.txt","w",stdout)typedef long long LL;const LL mod=1e9+7;const int INF=0x3f3f3f3f;const double PI=acos(-1.0);using namespace std;const int N=50005;LL a[N];LL pos[N];LL temp[N];LL ans;struct node{    LL l;    LL r;    LL index;    LL a,b;}Q[N];bool cmp1(node x,node y){    return pos[x.l]==pos[y.l]?x.r<y.r:x.l<y.l;}bool cmp2(node x,node y){    return x.index<y.index;}void mdy(int i,int add){    ans+=(LL)(2*add*temp[a[i]]+1);    temp[a[i]]+=add;}LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}int main (){    LL n,m;    scanf ("%lld%lld",&n,&m);    int div=(int)sqrt(n*1.0);    for (int i=1;i<=n;i++) scanf("%lld",&a[i]),pos[i]=(i-1)/div+1;//   i 在第pos[i]块    for (int i=1;i<=m;i++){        scanf ("%lld%lld",&Q[i].l,&Q[i].r);        Q[i].index=i;    }    sort(Q+1,Q+m+1,cmp1);//      分块后的排序    int ll=1,rr=0;    ans=0;    for (int i=1;i<=m;i++){        while (rr<Q[i].r) rr++,mdy(rr,1);        while (rr>Q[i].r) mdy(rr,-1),rr--;        while (ll<Q[i].l) mdy(ll,-1),ll++;        while (ll>Q[i].l) ll--,mdy(ll,1);        if (Q[i].l==Q[i].r){            Q[i].a=0;Q[i].b=1;            continue;        }        Q[i].a=ans-(Q[i].r-Q[i].l+1);        Q[i].b=(LL)((Q[i].r-Q[i].l+1)*(Q[i].r-Q[i].l));        LL k=gcd(Q[i].a,Q[i].b);        Q[i].a/=k;Q[i].b/=k;    }    sort(Q+1,Q+m+1,cmp2);//     找回原序列    for (int i=1;i<=m;i++) printf("%lld/%lld\n",Q[i].a,Q[i].b);    return 0;}

阅读全文
0 0
原创粉丝点击