BZOJ 2038 莫队

(我不会告诉你我是抄的黄学长的题解的……)

//By SiriusRen
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
#define N 100050
int n,m,a[N],pos[N],ans,ch[N];
struct Ask{int x,y,id,ansx,ansy;}ask[N];
bool cmp(Ask a,Ask b){
    if(pos[a.x]==pos[b.x])return a.y<b.y;
    return a.x<b.x;
}
bool cmp2(Ask a,Ask b){return a.id<b.id;}
int gcd(int x,int y){return y?gcd(y,x%y):x;}
void update(int num,int wei){
    ans-=ch[a[num]]*ch[a[num]];
    ch[a[num]]+=wei;
    ans+=ch[a[num]]*ch[a[num]];
}
signed main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    int block=sqrt(n);
    for(int i=1;i<=n;i++)
        pos[i]=(i-1)/block+1;
    for(int i=1;i<=m;ask[i].id=i,i++)
        scanf("%lld%lld",&ask[i].x,&ask[i].y);
    sort(ask+1,ask+1+m,cmp);
    for(int i=1,l=1,r=0;i<=m;i++){
        for(;r<ask[i].y;r++)update(r+1,1);
        for(;r>ask[i].y;r--)update(r,-1);
        for(;l<ask[i].x;l++)update(l,-1);
        for(;l>ask[i].x;l--)update(l-1,1);
        if(ask[i].x==ask[i].y){
            ask[i].ansx=0,ask[i].ansy=1;
            continue;
        }
        ask[i].ansx=ans-(r-l+1);
        ask[i].ansy=(r-l+1)*(r-l);
        int GCD=gcd(ask[i].ansx,ask[i].ansy);
        ask[i].ansx=ask[i].ansx/GCD,ask[i].ansy=ask[i].ansy/GCD;
    }
    sort(ask+1,ask+1+m,cmp2);
    for(int i=1;i<=m;i++){
        printf("%lld/%lld\n",ask[i].ansx,ask[i].ansy);
    }
}

这里写图片描述

posted @ 2016-12-20 21:55  SiriusRen  阅读(121)  评论(0编辑  收藏  举报