【BZOJ 2038】小Z的袜子

【题目链接】

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

【算法】

           莫队算法

【代码】

            

#include<bits/stdc++.h>
using namespace std;
#define MAXN 50010
typedef long long ll;

struct info
{
        ll x,y;
} ans[MAXN];
struct Query
{
        ll l,r,id;        
} q[MAXN],tmp[MAXN];

ll i,j,n,m,len,block,t,sum,l,r,k,g;
ll a[MAXN],num[MAXN];

inline ll gcd(ll x,ll y)
{
        return y == 0 ? x : gcd(y,x%y);        
}
inline bool cmp1(Query a,Query b)
{
        return a.l < b.l;
}
inline bool cmp2(Query a,Query b)
{
        return a.r < b.r;
}
inline void add(ll l,ll r,ll val)
{
        ll i;
        for (i = l; i <= r; i++)
        {
                sum -= num[a[i]] * (num[a[i]] - 1);
                num[a[i]] += val;
                sum += num[a[i]] * (num[a[i]] - 1);
        } 
}

int main() 
{
        
        scanf("%lld%lld",&n,&m);
        for (i = 1; i <= n; i++) scanf("%lld",&a[i]);
        for (i = 1; i <= m; i++) 
        {
                scanf("%lld%lld",&q[i].l,&q[i].r);
                q[i].id = i;
        }
        sort(q+1,q+m+1,cmp1);
        len = sqrt(n);
        block = n / len + (n % len != 0);
        j = 1;
        for (i = 1; i <= block; i++) 
        {
                t = 0; sum = 0;
                while (j <= m && q[j].l > (i - 1) * len && q[j].l <= i * len) 
                {
                        tmp[++t] = q[j];
                        j++;
                }
                memset(num,0,sizeof(num)); 
                sort(tmp+1,tmp+t+1,cmp2);
                l = tmp[1].l; r = tmp[1].l - 1;
                for (k = 1; k <= t; k++)
                {
                        if (l < tmp[k].l) add(l,tmp[k].l-1,-1);
                        else if (l > tmp[k].l) add(tmp[k].l,l-1,1);
                        add(r+1,tmp[k].r,1);
                        l = tmp[k].l; r = tmp[k].r;
                        ans[tmp[k].id].x = sum;
                        ans[tmp[k].id].y = (tmp[k].r - tmp[k].l + 1) * (tmp[k].r - tmp[k].l);
                }
        } 
        for (i = 1; i <= m; i++)
        {
                if (!ans[i].x) printf("0/1\n");
                else 
                {
                        g = gcd(ans[i].x,ans[i].y);
                        ans[i].x /= g;
                        ans[i].y /= g;
                        printf("%lld/%lld\n",ans[i].x,ans[i].y);
                }
        }
        return 0;
    
}

 

posted @ 2018-07-14 16:56  evenbao  阅读(125)  评论(0编辑  收藏  举报