【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; }